C共享对象,带有c++归档,静态变量/变量,和开放

C Shared Object, With C++ Archive, Static Ctors/Dtors, and dlopen

本文关键字:变量 静态 归档 共享 对象 带有 c++      更新时间:2023-10-16

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

在Ubuntu上,当打开RTLD_GLOBALRTLD_GLOBAL | RTLD_LAZY的共享库时,静态初始化器似乎没有运行。我看到的症状是程序崩溃。

我所看到的行为似乎与-nostartfiles-nostdlib链接相似(但我不使用它们)。我在 c++静态构造函数和开放的共享库中发现了一个类似的线程,但它用于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时运行?

在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