【问题标题】:Dynamic library problems with Python and libstdc++Python 和 libstdc++ 的动态库问题
【发布时间】:2011-09-26 21:37:38
【问题描述】:

执行摘要:Python 模块链接到的 libstdc++.dylib 版本与 Python 可执行文件不同。结果是从模块崩溃中调用iostream

背景故事

我正在一台旧计算机(运行 10.5.8)上使用 SWIG 创建一个 Python 模块。由于各种原因,我使用 GCC 4.5(通过 MacPorts 安装)来执行此操作,使用 Python 2.7(通过 MacPorts 安装,使用系统默认的 GCC 4.0.1 编译)。

观察到的行为

长话短说:在 Python 中调用 str( myObject ) 会导致 C++ 代码依次调用 std::operator<< <std::char_traits<char> >。这会产生以下错误:

Python(487) malloc: *** error for object 0x69548c: Non-aligned pointer being freed
*** set a breakpoint in malloc_error_break to debug

设置断点并在失败时调用backtrace

#0  0x9734de68 in malloc_error_break ()
#1  0x97348ad0 in szone_error ()
#2  0x97e6fdfc in std::string::_Rep::_M_destroy ()
#3  0x97e71388 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string ()
#4  0x97e6b748 in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow ()
#5  0x97e6e7a0 in std::basic_streambuf<char, std::char_traits<char> >::xsputn ()
#6  0x00641638 in std::__ostream_insert<char, std::char_traits<char> > ()
#7  0x006418d0 in std::operator<< <std::char_traits<char> > ()
#8  0x01083058 in meshLib::operator<< <tranSupport::Dimension<(unsigned short)1> > (os=@0xbfffc628, c=@0x5a3c50) at /Users/sethrj/_code/pytrt/meshlib/oned/Cell.cpp:21
#9  0x01008b14 in meshLib_Cell_Sl_tranSupport_Dimension_Sl_1u_Sg__Sg____str__ (self=0x5a3c50) at /Users/sethrj/_code/_build/pytrt-gcc45DEBUG/meshlib/swig/mesh_onedPYTHON_wrap.cxx:4439
#10 0x0101d150 in _wrap_Cell_T___str__ (args=0x17eb470) at /Users/sethrj/_code/_build/pytrt-gcc45DEBUG/meshlib/swig/mesh_onedPYTHON_wrap.cxx:8341
#11 0x002f2350 in PyEval_EvalFrameEx ()
#12 0x002f4bb4 in PyEval_EvalCodeEx ()
[snip]

疑似问题

我认为问题在于我的代码链接到新版本的 libstdc++:

/opt/local/lib/gcc45/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.14.0)

而 Python 二进制文件非常间接地依赖于系统 libstdc++,它首先加载(从 gdb 中的 info shared 输出):

  1 dyld                  - 0x8fe00000        dyld Y Y /usr/lib/dyld at 0x8fe00000 (offset 0x0) with prefix "__dyld_"
  2 Python                - 0x1000            exec Y Y /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python (offset 0x0)
                                          (objfile is) /opt/local/bin/python
  3 Python                F 0x219000          dyld Y Y /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Python at 0x219000 (offset 0x219000)
  4 libSystem.B.dylib     - 0x9723d000        dyld Y Y /usr/lib/libSystem.B.dylib at 0x9723d000 (offset -0x68dc3000)
                                 (commpage objfile is) /usr/lib/libSystem.B.dylib[LC_SEGMENT.__DATA.__commpage]
  5 CoreFoundation        F 0x970b3000        dyld Y Y /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation at 0x970b3000 (offset -0x68f4d000)
  6 libgcc_s.1.dylib      - 0x923e6000        dyld Y Y /usr/lib/libgcc_s.1.dylib at 0x923e6000 (offset -0x6dc1a000)
  7 libmathCommon.A.dylib - 0x94af5000        dyld Y Y /usr/lib/system/libmathCommon.A.dylib at 0x94af5000 (offset -0x6b50b000)
  8 libicucore.A.dylib    - 0x97cf4000        dyld Y Y /usr/lib/libicucore.A.dylib at 0x97cf4000 (offset -0x6830c000)
  9 libobjc.A.dylib       - 0x926f0000        dyld Y Y /usr/lib/libobjc.A.dylib at 0x926f0000 (offset -0x6d910000)
                                 (commpage objfile is) /usr/lib/libobjc.A.dylib[LC_SEGMENT.__DATA.__commpage]
 10 libauto.dylib         - 0x95eac000        dyld Y Y /usr/lib/libauto.dylib at 0x95eac000 (offset -0x6a154000)
 11 libstdc++.6.0.4.dylib - 0x97e3d000        dyld Y Y /usr/lib/libstdc++.6.0.4.dylib at 0x97e3d000 (offset -0x681c3000)
 12 _mesh_oned.so         - 0x1000000         dyld Y Y /Users/sethrj/_code/_build/pytrt-gcc45DEBUG/meshlib/swig/_mesh_oned.so at 0x1000000 (offset 0x1000000)
 13 libhdf5.7.dylib       - 0x122c000         dyld Y Y /opt/local/lib/libhdf5.7.dylib at 0x122c000 (offset 0x122c000)
 14 libz.1.2.5.dylib      - 0x133000          dyld Y Y /opt/local/lib/libz.1.2.5.dylib at 0x133000 (offset 0x133000)
 15 libstdc++.6.dylib     - 0x600000          dyld Y Y /opt/local/lib/gcc45/libstdc++.6.dylib at 0x600000 (offset 0x600000)
[snip]

请注意,malloc 错误发生在系统 libstdc++ 的内存地址中,而不是共享库所链接的那个。

尝试的解决方案

我试图强制 MacPorts 使用 GCC 4.5 而不是 Apple 编译器来构建 Python,但安装阶段失败了,因为它需要创建一个 Mac“框架”,而普通 GCC 显然不这样做。

即使使用 -static-libstdc++ 编译器标志,__ostream_insert 也会从系统加载的共享库中调用 std::basic_streambuf

我尝试通过添加 /opt/local/lib/gcc45/ 来修改 DYLD_LIBRARY_PATH,但无济于事。

我该怎么做才能让它发挥作用?我已经束手无策了。

更多信息

这个问题好像是common to mac os x。请注意,在所有调试输出中,地址如何在对std::__ostream_insertstd::basic_streambuf::xsputn 的调用之间跳转:它离开了新的GCC 4.5 代码并跳转到/usr/bin 中的旧共享库代码。现在,要找到解决方法...

【问题讨论】:

  • 虽然 Python 对编译器和库版本来说真的很烦人,但这似乎是您的特殊问题。您确定您的代码不会用指针(如字符串对象)做一些有趣的事情吗?您是否尝试过以不同的方式组合字符串(字符串 +、sprintf 等)?
  • MacPorts 端口文件旨在与 Apple 提供的 (Xcode) gcc 工具链一起安装,除非另有说明。您将迎难而上,试图改变 MacPorts 构建 Python 及其所有依赖项的方式。 MacPorts swig-python 端口不起作用?`
  • 是的,这是使用 MacPorts swig-python,我确信代码完全合法。在使用相同代码编译的独立 C++ 可执行文件中,它可以正常工作。我已经仔细检查了构建链中的每个阶段。 (我也使用 -Wall -Wextra。)
  • 这可能是线程安全问题,尤其是在您更改流转换中的语言环境时?
  • 遇到了类似的问题herehere。一个共享库中的 __ostream_insert 中的代码调用了另一个共享库中的 xsputn,它们似乎是二进制不兼容的。

标签: python macos gcc dll macports


【解决方案1】:

解决了。我发现在 mac 上混合 GCC 版本时,这个问题并不少见。在阅读this solution for mpich并检查mpich source code后,我发现解决方案是在mac系统上将以下标志添加到gcc:

-flat_namespace

我很高兴。我希望这没有花我一个星期的时间来弄清楚。 :)

【讨论】:

    【解决方案2】:

    在 GDB 中运行 Python,在 malloc_error_break 上设置断点。这将向您显示未分配的正在释放的内容。我怀疑这是 libstdc++ 版本之间的 ABI 之间的错误。

    【讨论】:

    • 你读过这个问题吗?那是我发布的输出。这是malloc_error_break 中的一个断点,从0x97------ 内存空间调用,这是旧libstdc++ 的加载位置。
    猜你喜欢
    • 2019-07-10
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多