Python 和 libstdc 的动态库问题++
执行摘要:Python 模块链接到与 Python 可执行文件不同的 libstdc++.dylib
版本。结果是模块中对 iostream 的调用崩溃。
背景故事
我正在一台旧计算机(运行 10.5.8)上使用 SWIG 创建一个 Python 模块。由于各种原因,我使用 GCC 4.5(通过 MacPorts 安装)来执行此操作,并使用 Python 2.7(通过 MacPorts 安装,使用系统默认的 GCC 4.0.1 编译)。
观察到的行为
长话短说:在 Python 中调用 str( myObject )
会导致 C++ 代码依次调用 std::operator<<
。这会生成以下错误:
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共享
的输出):
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 但无济于事。
我该怎么做才能让它发挥作用?我已经无计可施了。
更多信息
此问题似乎是 Mac 操作系统的常见问题x。请注意,在所有调试输出中,地址如何在对 std::__ostream_insert
和 std::basic_streambuf::xsputn
的调用之间跳转:它离开了新的 GCC 4.5代码并跳转到 /usr/bin
中较旧的共享库代码。现在,要找到解决方法...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解决了。我发现在 Mac 上混合 GCC 版本时这个问题并不少见。阅读此 mpich 解决方案并检查mpich源代码,我发现解决方案是在mac系统上的gcc中添加以下标志:
我太高兴了。我希望这没有花费我一周的时间来弄清楚。 :)
Solved it. I discovered that this problem is not too uncommon when mixing GCC versions on the mac. After reading this solution for mpich and checking the mpich source code, I found that the solution is to add the following flag to gcc on mac systems:
I am so happy. I wish this hadn't taken me a week to figure out. :)
在 GDB 中运行 Python,在
malloc_error_break
上设置断点。这将向您显示正在释放但未分配的内容。我怀疑这是 libstdc++ 版本之间的 ABI 之间的错误。Run Python in GDB, set a breakpoint on
malloc_error_break
. That will show you what's being freed that's not allocated. I doubt that this is an error between ABIs between the versions of libstdc++.