1

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

RTLD_GLOBAL在 Ubuntu 上,使用和打开共享库时,静态初始化程序似乎没有运行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'd 时运行静态初始化程序?

4

1 回答 1

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
于 2013-05-03T06:07:26.603 回答