在为Ruby开发SWIG包装的C ++库时,我们在C ++代码中的异常处理期间遇到了无法解释的崩溃。
我不确定重新创建问题的具体情况,但它在调用std::uncaught_exception
时首先发生,然后在一些代码更改后,在异常构建期间移至__cxa_allocate_exception
。 GDB和valgrind都没有提供有关崩溃原因的任何见解。
我发现了几个类似问题的引用,包括:
最重要的主题似乎是情况的组合:
“解决方案”是将您的库与libstdc ++以及可能还与libGL明确地链接,从而强制链接的顺序。
尝试使用我的代码进行多次组合后,我发现唯一有效的解决方案是LD_PRELOAD="libGL.so libstdc++.so.6" ruby scriptname
选项。也就是说,编译时链接解决方案都没有任何区别。
我对该问题的理解是C ++运行时未正确初始化。通过强制链接的顺序,您可以引导初始化过程并且它可以正常工作。只有C应用程序调用C ++库时才会出现此问题,因为C应用程序本身并不链接到libstdc ++,并且没有初始化C ++运行时。因为使用SWIG(或boost :: python)是从C应用程序调用C ++库的常用方法,所以在研究问题时经常出现SWIG。
是否有人能够更深入地了解这个问题?是否存在实际解决方案或仅存在解决方法?
感谢。
答案 0 :(得分:6)
根据迈克尔·多根的建议,我将我的评论复制到答案中:
找到问题的真正原因。希望这会帮助其他人遇到这个bug。您可能在某处未正确初始化的某些静态数据。我们做了,解决方案是我们的代码库的boost-log。 https://sourceforge.net/projects/boost-log/forums/forum/710022/topic/3706109。真正的问题是延迟加载库(加上静态),而不是来自不同库的潜在的多个C ++版本。有关详细信息:http://parashift.com/c++-faq-lite/ctors.html#faq-10.13
自从遇到这个问题及其解决方案以来,我了解到了解静态和动态链接库之间如何共享或不共享静态非常重要。在Windows上,这需要显式导出共享静态的符号(包括意味着跨不同库访问的单例)。每个主要平台之间的行为略有不同。
答案 1 :(得分:3)
我最近遇到了这个问题。我的进程创建了一个用作python C ++扩展的共享对象模块。最近从RHEL 6.4升级到6.5的操作系统暴露了这个问题。
按照这里的提示,我只是将-lstdc ++添加到我的链接开关中,这解决了问题。
答案 2 :(得分:1)
使用SWIG for Python和cpp库(Clipper)有同样的问题,我发现使用LD_PRELOAD就像你建议的那样也适用于我。 作为另一个不需要LD_PRELOAD的解决方法,我发现我也可以将libstdc ++链接到我模块的.so库文件中,例如。
ld -shared /usr/lib/i386-linux-gnu/libstdc++.so.6 module.o module_wrap.o -o _module.so
然后我可以在python中导入它而不需要任何其他选项。
答案 3 :(得分:1)
我意识到@lefticus接受了与我猜测的未定义的静态init顺序相关的答案;但是,我有一个非常类似的问题,这次是boost::python
。
我尽力找到任何静态启动问题而且不能 - 我重构了我们代码库的一大部分;当这不起作用时最终完全删除了例外。
然而,更多人悄悄进入,我们又开始了解这些段错误。
经过一番调查后,我遇到了this link,其中讨论了自定义分配器。
我们确实自己使用tcmalloc
;在我从导出到boost::python
的库中删除它后,我们没有更多问题了!
所以对于任何偶然发现这个帖子的人来说只是一个FYI - 如果@ lefticus的答案不起作用,请检查你是否使用了与python
使用的分配器不同的分配器。