【问题标题】:segfault during __cxa_allocate_exception in SWIG wrapped librarySWIG 包装库中 __cxa_allocate_exception 期间的段错误
【发布时间】:2011-02-16 05:13:12
【问题描述】:

在为 Ruby 开发一个 SWIG 封装的 C++ 库时,我们在 C++ 代码内的异常处理过程中遇到了无法解释的崩溃。

我不确定重新创建问题的具体情况,但它首先发生在调用std::uncaught_exception 期间,然后在一些代码更改后,在异常构造期间移至__cxa_allocate_exception。 GDB 和 valgrind 都没有提供任何有关崩溃原因的见解。

我找到了几个类似问题的参考资料,包括:

最重要的主题似乎是多种情况的组合:

  • 一个 C 应用程序链接到多个 C++ 库
  • 编译期间使用了多个版本的 libstdc++
  • 通常使用的第二个 C++ 版本来自 libGL 的仅二进制实现
  • 将库与 C++ 应用程序链接时不会出现此问题,仅与 C 应用程序链接

“解决方案”是将您的库与 libstdc++ 以及可能还与 libGL 显式链接,强制链接顺序。

在我的代码尝试了许多组合之后,我发现唯一可行的解​​决方案是LD_PRELOAD="libGL.so libstdc++.so.6" ruby scriptname 选项。也就是说,编译时链接解决方案都没有任何区别。

我对这个问题的理解是 C++ 运行时没有被正确初始化。通过强制链接顺序,您可以引导初始化过程并且它可以工作。该问题仅发生在调用 C++ 库的 C 应用程序中,因为 C 应用程序本身并没有链接到 libstdc++ 并且没有初始化 C++ 运行时。因为使用 SWIG(或 boost::python)是从 C 应用程序调用 C++ 库的常用方法,所以在研究问题时经常会出现 SWIG。

有没有人能够更深入地了解这个问题?是否有实际的解决方案或仅存在变通方法?

谢谢。

【问题讨论】:

标签: c++ linux exception g++ segmentation-fault


【解决方案1】:

我最近也遇到了这个问题。我的过程创建了一个共享对象模块,该模块用作 python C++ 扩展。最近从 RHEL 6.4 升级到 6.5 的操作系统暴露了这个问题。

按照此处的提示,我只是将 -lstdc++ 添加到我的链接开关中并解决了问题。

【讨论】:

    【解决方案2】:

    我意识到@lefticus 接受了与我猜想相当于未定义的静态初始化顺序有关的答案;但是,我遇到了一个非常相似的问题,这次是boost::python

    我尽了最大的努力去发现任何静态初始化问题,但没有找到——以至于我重构了我们代码库的主要部分;当这不起作用时,最终会完全删除异常。

    然而,更多的人悄悄进入,我们又开始遇到这些段错误。

    经过进一步调查,我遇到了this link,它谈到了自定义分配器。

    我们自己确实使用tcmalloc;在我将它从导出到boost::python 的库中删除后,我们就再也没有问题了!

    因此,对于偶然发现此线程的任何人,仅供参考 - 如果 @lefticus 的答案不起作用,请检查您使用的分配器是否与 python 使用的分配器不同。

    【讨论】:

      【解决方案3】:

      在使用带有 cpp 库 (Clipper) 的 SWIG for Python 时遇到同样的问题,我发现按照您的建议使用 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。

      【讨论】:

        【解决方案4】:

        根据 Michael Dorgan 的建议,我将我的评论复制到答案中:

        找到问题的真正原因。希望这将帮助其他遇到此错误的人。您可能在某处有一些未正确初始化的静态数据。我们做到了,解决方案在我们代码库的 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 上,这需要显式导出共享静态的符号(包括旨在跨不同库访问的单例)。每个主要平台之间的行为略有不同。

        【讨论】:

        • 也接受这个作为答案:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多