c++ - std::thread 在使用-static-libstdc++ 时变弱,从而导致运行时崩溃

标签 c++ linux shared-libraries libstdc++ gcc5

我需要构建一个可移植的共享对象,它是 Linux 上另一个软件的插件。我对这个主题做了一些阅读,得出的结论是,我应该用一个相当老的 glibc(以提供与旧系统的兼容性)构建一个 sysrooted gcc(如果重要的话,gcc 5.4.0),链接 -static-libstdc++-static-libgcc 从而达到了这样一个地步,我有一些东西只依赖于主机 glibc 和其他一些小东西将永远存在。

现在,我做了所有这些,现在我遇到了一个奇怪的崩溃——段错误发生在代码调用 std::thread 的地方,而 gdb 实际上显示堆栈帧在里面libstdc++.so.6(不应该的地方,我的共享对象的ldd也没有列出libstdc++.so)。崩溃时的栈顶是:

#0  0x0000000000000000 in ?? ()
#1  0x00007ffff79075e3 in std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void (*)()) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 # THIS SHOULD NOT BE HERE RIGHT?
#2  0x00007ffff5a25a5c in std::thread::thread<void (ReferenceAnalytics::*)(std::timed_mutex&), ReferenceAnalytics*&, std::reference_wrapper<std::timed_mutex> >
    (this=0x7fffffffcf40, __f=
    @0x7fffffffcf60: (void (ReferenceAnalytics::*)(ReferenceAnalytics * const, std::timed_mutex &)) 0x7ffff5a1750c <ReferenceAnalytics::WorkerThreadMethod(std::timed_mutex&)>)
    at /home/developer/Toolchains/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/include/c++/5.4.0/thread:137 # Looks like my toolchain

所以,我做了一些阅读,然后使用 nm 发现我的共享对象具有所有 std::thread 东西,比如 ctor、dtor、swap、.. .. 定义为弱符号(我假设如果加载插件的主机使用动态 libstdc++ 会导致冲突,然后我的调用被路由到那里并且一切都崩溃了,对吗?)。

我进一步尝试谷歌搜索和阅读并没有给我一个答案,我该如何控制它,因为强制 std::thread 东西被解析为静态 libstdc++ 在我的 sysrooted gcc 中?

此外,我制作了一个小的可执行文件,它只是在我的共享对象上执行 dlopen,然后调用一个在内部构造线程的方法 - 如果可执行文件也是用 -static- 构建的libstdc++ 一切正常,否则会崩溃。所以我假设我关于 std::thread 的弱符号被解析为主机 libstdc++ 的理论是正确的,但如何解决这个问题?

最佳答案

如果您在不隐藏 libstdc++ 符号的情况下将 DSO 静态链接到 libstdc++,并且主程序也链接到 libstdc++,则主程序中的符号定义将在 DSO 打开时插入/抢占 DSO 中的定义dlopen.

但是,由于主程序未链接到 libpthread,过程镜像中的系统 libstdc++ DSO 发现 libpthread 符号不可用(空),因此禁用了线程支持。但是,您的 DSO 需要线程支持,但无法从系统 libstdc++ 中获取。

作为一种直接的解决方法,您可以在 DSO 中隐藏所有静态链接的 libstdc++ 符号。然后不会进行任何干预,您的 DSO 将实际使用 DSO 本身中的 libstdc++ 拷贝,这已经确定该过程中不应有任何线程支持。

但这可能不会解决您所有的问题,因为通过 dlopen 延迟加载 libpthread 有其问题。我们在这里修复了一个错误:

但是你的发行版可能没有那个修复,我预计还会有其他问题,其中之一是:这里实际上需要 libstdc++ 的第二个静态链接拷贝,因为系统 libstdc++ 已经在没有线程支持的情况下加载(因为绑定(bind)符号时未加载 libpthread,导致您观察到的崩溃),因此您不能使用它来创建线程。它还激活了优化,使库不是线程安全的(避免原子指令和类似的东西)。

关于c++ - std::thread 在使用-static-libstdc++ 时变弱,从而导致运行时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51526304/

相关文章:

c++ - 对抗内存泄漏

android - Android 上的 pcsc-lite 和 ccid

linux - 在ubuntu中执行shell脚本

c - 动态链接 C 驱动程序后 undefined symbol

c++ - 获取 Qt 应用程序的 .so 依赖项的完整列表?

c++ - 创建 C++ Redis 模块 - "does not export RedisModule_OnLoad() symbol"

c++ - FLTK:如何通过拖动使小部件可调整大小?

c++ - C++/SFML 中的平稳动量减速?

c++ - Windows 10 VersionHelper.h

linux - 提供 Node.JS webapp "key in hand"