Skip to content

Explicit Template Instantiation

ZengJingtao edited this page Jan 30, 2023 · 2 revisions

template explicit instantiation

Background

Currently, Topling SidePlugin is directly compiled into librocksdb.so. The reason for this is that for static libraries, the linker will automatically delete symbols it considers useless. If all symbols in a compilation unit of the linker are not used, the entire compilation The code of the unit will be deleted. To get around this, you can use --whole-archive, but that also links in a lot of really useless code.

At present, we have not found a perfect solution to this problem, so we use the dynamic library librocksdb.so.

Then I encountered another problem when using the dynamic library: For the static variables in the function of the template class in the header file, there will be problems when there are multiple so. In our scenario, in addition to librocksdb.so, there is also a user plugin library libuserplugin.so, in these two sos, will automatically register plugins (through the construction/destruction of the global object), and these plugins will have double-free problems when they are destructed.

Analysis

After diagnostic analysis, it is basically confirmed that it is caused by the imperfection of the compiler/linker, because according to speculation:

  1. Multiple compilation units will have the same template instantiation code (represented by the same function ID/symbol)
  2. When linking, for repeated symbols, only one copy is kept
  3. When linking, if the input .o file and the .so file have the same symbols, the linker will use the symbols in .so and discard the symbols in .o (and the corresponding codes and objects)
  4. According to the dependency relationship, the object constructed first will be destructed, and the object in the .so at the end of the dependency relationship will be destructed last

If the above 4 points are all established, there will be no problem. However, the performance of the program is that there is no problem when constructing (registering the plug-in), but a double-free error occurs when destructing, so the actual situation does not match at least one of the above 3rd and 4th items.

Solution

Obviously we can't change the compiler, and we're unlikely to submit a bug to the compiler and wait for the bug to be fixed.

The approach we take is: explicit instantiation. A header file that contains only the template declaration, and a separate side_plugin_tpl_inst.cc file that includes the template's implementation and explicit instantiation.

Explicit instantiation not only solves the problem of double free, but also produces additional benefits:

  1. Other bug found and fixed: implicit instantiation of wrong type
  2. Reduced object code size
  3. faster compilation