plugin1.cpp:
#include <iostream>
static class TestStatic {
public:
TestStatic() {
std::cout << "TestStatic create" << std::endl;
}
~TestStatic() {
std::cout << "TestStatic destroy" << std::endl;
}
} test_static;
host.cpp
#include <dlfcn.h>
#include <iostream>
int main(int argc,char *argv[]) {
void* handle = dlopen("./plugin1.so",RTLD_NOW | RTLD_LOCAL );
dlclose(handle);
return 0;
}
build and run:
>g++ -c plugin1.cpp -o plugin1.o -fPIC
>g++ -shared plugin.o -o plugin1.so
>g++ host.cpp -o host -ldl
>./host
>TestStatic create
>Segmentation fault
why TestStatic::~TestStatic called at ‘exit()’ but not at ‘dlclose()’ ?
This problem is addressed in later versions of GCC including C/C++ standard library and linker. Basically, C++ destructors should be registered using
__cxa_atexitfunction instead ofatexit(3).For the full technical details on
__cxa_atexit, see Itanium C++ ABI specification.It is not clear from your question what version of the gcc, linker and standard C library you are using. Plus, the code you have provided does not meet POSIX standard as there are no
RTDL_NOWorRTDL_LOCALmacros defined. They areRTLD_NOWandRTLD_LOCAL(see dlopen).If your C standard library does not support
__cxa_atexit, you may need to disable it by specifying-fno-use-cxa-atexitgcc flag:But that might result in a problem where destructors are called in different order or not called at all. So the best solution in case of broken
__cxa_atexitsupport or no support at all is not to use static objects with destructors in your shared libraries.