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

时间:2018-07-25 19:25:44

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

我需要构建一个可移植的共享对象,它是Linux上另一个软件的插件。我对该主题做了一些阅读,最后得出结论,我应该使用一个相当老的glibc(以提供与旧系统的兼容性)构建一个以sysroot为基础的gcc(如果重要的话,请使用gcc 5.4.0),并与{{ 1}}和-static-libstdc++到了这样的地步,我所拥有的东西仅取决于主机-static-libgcc和其他一些永远存在的次要东西。

现在,我做了所有这些,现在遇到了奇怪的崩溃-分段错误发生在代码调用glibc的地方,而gdb实际上表明堆栈帧在std::thread内部(我的共享对象的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东西,例如ctor,dtor,swap,...。都定义为弱符号(我将如果加载插件的主机使用动态std::thread,并且我的电话被路由到那里并且所有地狱都松散了,则假设会导致冲突。

我进一步的谷歌搜索和阅读尝试并没有给我一个答案,我该如何控制该问题,因为libstdc++的内容被强制解析为我的根系gcc中的静态std::thread? >

此外,我制作了一个小的可执行文件,该文件仅对共享对象执行libstdc++,然后调用一个内部构造线程的方法-如果该可执行文件也是使用dlopen构建的,那么一切都很好,如果没有,崩溃就会发生。因此,我假设我关于将-static-libstdc++的弱符号解析为主机std::thread的理论是正确的,但是如何解决呢?

1 个答案:

答案 0 :(得分:1)

如果在不隐藏libstdc ++符号的情况下静态链接DSO与libstdc ++,并且主程序也与libstdc ++链接,那么当使用DSO打开DSO时,主程序中的符号定义将插入/抢占DSO中的定义。 dlopen

但是,由于主程序未针对libpthread进行链接,因此过程映像中的系统libstdc ++ DSO看到libpthread符号不可用(空),因此禁用了线程支持。但是,您的DSO需要线程支持,但无法从系统libstdc ++获得它。

作为一种直接的解决方法,您可以在DSO中隐藏所有静态链接的libstdc ++符号。这样就不会发生任何介入,并且您的DSO实际上将在DSO本身中使用libstdc ++副本,该副本已确定该过程中不应有任何线程支持。

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

但是您的发行版可能没有此修复程序,我希望还会有其他问题,其中一个是:这里实际上需要libstdc ++的第二个静态链接副本,因为系统libstdc ++的加载没有线程支持(因为绑定符号时,libpthread没有加载,从而导致您观察到的崩溃),因此您不能使用它来创建线程。它还具有激活的优化功能,这些功能使该库不是线程安全的(避免使用原子指令等)。