I am creating a shared library "libMyLibrary.so" with the class "MyClass", which contains a static variable like "MyClass". Then I create the executable file "MyLibraryTest", which I link to "libMyLibrary.so". The main program uses "dlopen" to dynamically load ".so" as an argument.
When building a library and an executable file are generated in the directory, for example, "buildDir / bin". Then I install the library in "installDir / lib" and the executable in "installDir / bin" (removing the execution path from the executable).
When I run "buildDir / MyLibraryTest buildDir / MyLibrary.so" with LD_LIBRARY_PATH = buildDir, everything is fine.
But when I run "buildDir / MyLibraryTest installDir / lib / MyLibrary.so" with LD_LIBRARY_PATH = installDir / lib, a very strange thing occurs: - The static variable constructor is called twice (once before dlopen, once during dlopen) - At the end of execution the destructor is called twice, and this leads to a failure.
Here is my code:
Myclass.h
#ifndef _MyClass_h__ #define _MyClass_h__ #include <string> class MyClass { private: static MyClass myStaticObjOfMyClass; public: MyClass(const std::string& name, bool trace); virtual ~MyClass(); private: std::string myName; bool myTrace; }; #endif // _MyClass_h__
Myclass.cpp
#include "MyClass.h" #include <iostream> MyClass MyClass::myStaticObjOfMyClass("myStaticObjOfMyClass", true); MyClass::MyClass(const std::string& name, bool trace) : myName(name), myTrace(trace) { if (myTrace) std::cout << "MyClass::MyClass(name=" << myName << ", address=" << this << ")" << std::endl; } MyClass::~MyClass() { if (myTrace) std::cout << "MyClass::~MyClass(name=" << myName << ", address=" << this << ")" << std::endl; }
MyLibraryTest.cpp
#include <MyClass.h> #include <iostream> #include <string> #include <dlfcn.h> int main(int argc, char* argv[]) { const std::string sharedLibraryFullName((const char*)argv[1]); // std::cout << "Try to load library " << sharedLibraryFullName << std::endl; void* handle = NULL; std::cout << "dlopen(" << sharedLibraryFullName << ")" << std::endl; handle = dlopen(sharedLibraryFullName.c_str(), RTLD_LAZY | RTLD_GLOBAL); if (handle == NULL) { std::cout << "ERROR : Could not load shared library " << sharedLibraryFullName << std::endl; } else { std::cout << "OK, shared library " << sharedLibraryFullName << " is now loaded" << std::endl; } }
Here are the compilation commands and links:
/usr/local/bin/g++ -DMyLibrary_DEFINED -DMyLibrary_EXPORTS -O3 -DNDEBUG -fPIC -o CMakeFiles/MyLibrary.dir/MyClass.cpp.o -c MyClass.cpp /usr/local/bin/g++ -fPIC -O3 -DNDEBUG -shared -Wl,-soname,libMyLibrary.so -o ../bin/libMyLibrary.so CMakeFiles/MyLibrary.dir/MyClass.cpp.o
And finally, here's what happens in the second case (duplicate initialization of a static variable):
MyClass::MyClass(name=myStaticObjOfMyClass, address=0x7fa710cabb40) dlopen(/tmp/Install/MyLibraryTest/lib/libMyLibrary.so) MyClass::MyClass(name=myStaticObjOfMyClass, address=0x7fa710cabb40) OK, shared library /tmp/Install/MyLibraryTest/lib/libMyLibrary.so is now loaded MyClass::~MyClass(name=myStaticObjOfMyClass, address=0x7fa710cabb40) MyClass::~MyClass(name= ObjOfMyClass, address=0x7fa710cabb40) *** glibc detected *** /tmp/Build/MyLibraryTest/Release/bin/MyLibraryTest: double free or corruption (fasttop): 0x0000000000cfb330 *** ======= Backtrace: ========= /lib64/libc.so.6[0x322f275dee] /lib64/libc.so.6[0x322f278c3d] /lib64/libc.so.6(__cxa_finalize+0x9d)[0x322f235d2d] /tmp/Build/MyLibraryTest/Release/bin/libMyLibrary.so(+0x1076)[0x7fa710aab076] ======= Memory map: ======== 00400000-00402000 r-xp 00000000 fd:00 1325638 /tmp/Build/MyLibraryTest/Release/bin/MyLibraryTest 00601000-00602000 rw-p 00001000 fd:00 1325638 /tmp/Build/MyLibraryTest/Release/bin/MyLibraryTest 00ce9000-00d1b000 rw-p 00000000 00:00 0 [heap] 322ee00000-322ee20000 r-xp 00000000 fd:00 545634 /lib64/ld-2.12.so 322f020000-322f021000 r
Any help would be greatly appreciated.