我有一个C共享对象,我正在加载dlopen
。 C共享对象包括另一个库作为静态存档(完全指定的路径/usr/local/.../libsomelib.a
)。 libsomelib.a
是一个C ++库,它具有全局和静态本地。
在Ubuntu上,使用RTLD_GLOBAL
和RTLD_GLOBAL | RTLD_LAZY
打开共享库时,静态初始值设定项似乎无法运行。我看到的症状是程序崩溃。
我看到的行为似乎与-nostartfiles
或-nostdlib
的链接类似(但我没有使用它们)。我在 C++ Static Constructors and dlopen'd Shared Libraries 找到了一个类似的线程,但是它用于NetBSD系统。
如果EXE显式包含libsomelib.a
并从中调用函数,则C ++库将初始化,并且在通过函数指针调用时程序不再崩溃。
编辑:这是共享对象的构建方式(这是我遇到的最简单的情况,没有混合/匹配C和C ++)。 cryptopp-so-test.exe
来电dlopen
:
CXXFLAGS = -g -ggdb -fPIC -DDEBUG -O1 -Wall -Wextra -Wno-unused -DUSE_PRECOMPILED_HEADERS=1 -I. -I/usr/local/include/cryptopp
...
precompile:
$(CXX) $(CXXFLAGS) pch.h -o pch.h.gch
cryptopp-so-test.exe: precompile $(EXEOBJECTS)
$(CXX) $(CXXFLAGS) -o $@ $(EXESOURCES) -ldl -lpthread
dsotest: precompile $(DLLOBJECTS)
$(CXX) $(CXXFLAGS) $(DLLSOURCES) -o dsotest-1.so -shared /usr/local/lib/libcryptopp.a
虽然上面的代码构建了一个EXE(cryptopp-so-test.exe)和一个SO(dsotest-1.so),但实际上我构建并加载了4个共享对象(它们的构建方式相同)。
当C ++组件的C共享对象为dlopen
时,我应该使用哪些标志(或其他方法)来确保运行静态初始化器?
答案 0 :(得分:1)
在Ubuntu上,使用RTLD_GLOBAL和RTLD_GLOBAL打开共享库时,静态初始化程序似乎不会运行RTLD_LAZY。
当您dlopen
共享库时,全局构造函数被调用。你可能会得出错误的结论。
我看到的症状是程序崩溃。
该症状可能由任何引起。您需要查看调试器中的崩溃,并了解导致它的原因,而不是盲目地猜测“静态初始化器”。
将libsomelib.a
链接到主可执行文件并将其链接到共享库之间的一个区别是,根据哪些代码调用哪些函数,最终可能会包含每个libsomelib.a
的不同部分(链接器只会引入它可以看到的libsomelib.a
部分。)
您可以尝试将整个 libsomelib.a
链接到共享库中,如下所示:
g++ $(OBJS) -o dsotest-1.so -shared \
-Wl,--whole-archive -lsomelib -Wl,--no-whole-archive