C共享对象,包含C ++存档,静态Ctors / Dtors和dlopen

时间:2013-04-24 16:35:49

标签: c++ shared-libraries dlopen

我有一个C共享对象,我正在加载dlopen。 C共享对象包括另一个库作为静态存档(完全指定的路径/usr/local/.../libsomelib.a)。 libsomelib.a是一个C ++库,它具有全局和静态本地。

在Ubuntu上,使用RTLD_GLOBALRTLD_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时,我应该使用哪些标志(或其他方法)来确保运行静态初始化器?

1 个答案:

答案 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