c++ - C 共享对象,带有 C++ 存档、静态 Ctors/Dtors 和 dlopen

标签 c++ shared-libraries dlopen

我有一个使用 dlopen 加载的 C 共享对象。 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 时,我应该使用什么标志(或其他方法)来确保静态初始化程序运行?

最佳答案

On Ubuntu, the static initializers do not appear to run when opening the shared library with RTLD_GLOBAL and RTLD_GLOBAL | RTLD_LAZY.

当您dlopen 共享库时,将调用全局构造函数。您可能会得出错误的结论。

The symptom I am seeing is a program crash.

该症状可能由任何引起。您需要查看调试器中的崩溃,并了解导致崩溃的原因,而不是盲目猜测“静态初始化程序”。

libsomelib.a 链接到主可执行文件和将其链接到共享库之间的一个区别是,根据哪个代码调用哪个函数,您最终可能会得到截然不同的 部分libsomelib.a 包含在每个文件中(链接器只会拉入它认为必要的 libsomelib.a 部分)。

您可以尝试将整个 libsomelib.a 链接到共享库中,如下所示:

g++ $(OBJS) -o dsotest-1.so -shared \
  -Wl,--whole-archive -lsomelib -Wl,--no-whole-archive

关于c++ - C 共享对象,带有 C++ 存档、静态 Ctors/Dtors 和 dlopen,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16197485/

相关文章:

c++ - Qt 无法将 OCR Tesseract 与 OpenCV 3.2 Ubuntu 一起使用

c++ - glibc : Test if lib as DF_1_NODELETE flag or if lib has unique symbol

c++ - 在 C++ 中使用 Matlab 数据结构?

c++ - std::vector 预分配(大小和容量 n + 2)

c++ - Scons - 使用带有 scons 缓存的自定义预处理器

c - 如何在不直接连接到它的其他库中调用库函数?

c++ - 链接 boost 库时引发 "Error while loading shared libraries",但我无法使用 root 访问权限来修复它

c# - 如何在 unix 系统上使 dotnet 核心库可从 dlopen 加载

c++ - 基于 dlopen 的应用程序第二次运行不同(错误)

c++ - Visual C++ 2010 拒绝在调试时显示 std::string 值。显示 <Bad Ptr>