Problemas de biblioteca dinámica con Python y libstdc ++

Resumen ejecutivo: un módulo de Python está vinculado a una versión diferente de libstdc++.dylib que el ejecutable de Python. El resultado es que las llamadas a iostream desde el módulo fallan.

Historia de fondo

Estoy creando un módulo Python usando SWIG en una computadora más antigua (con 10.5.8). Por varias razones, estoy usando GCC 4.5 (instalado a través de MacPorts) para hacer esto, usando Python 2.7 (instalado a través de MacPorts, comstackdo usando el GCC 4.0.1 predeterminado del sistema).

Comportamiento observado

Para std::operator<< <std::char_traits > historia: llamar a str( myObject ) en Python hace que el código C ++, a su vez, llame a std::operator<< <std::char_traits > . Esto genera el siguiente error:

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

Establecer un punto de interrupción y llamar a backtrace cuando falla da:

 #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, std::allocator >::~basic_string () #4 0x97e6b748 in std::basic_stringbuf<char, std::char_traits, std::allocator >::overflow () #5 0x97e6e7a0 in std::basic_streambuf<char, std::char_traits >::xsputn () #6 0x00641638 in std::__ostream_insert<char, std::char_traits > () #7 0x006418d0 in std::operator<< <std::char_traits > () #8 0x01083058 in meshLib::operator<< <tranSupport::Dimension > (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] 

Problema sospechado

Creo que el problema es que mi código se vincula con una nueva versión de libstdc ++:

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

mientras que el binario de Python tiene una dependencia muy indirecta del sistema libstdc++ , que se carga primero (salida de la info shared en gdb):

  1 dyld - 0x8fe00000 dyld YY /usr/lib/dyld at 0x8fe00000 (offset 0x0) with prefix "__dyld_" 2 Python - 0x1000 exec YY /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 YY /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Python at 0x219000 (offset 0x219000) 4 libSystem.B.dylib - 0x9723d000 dyld YY /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 YY /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation at 0x970b3000 (offset -0x68f4d000) 6 libgcc_s.1.dylib - 0x923e6000 dyld YY /usr/lib/libgcc_s.1.dylib at 0x923e6000 (offset -0x6dc1a000) 7 libmathCommon.A.dylib - 0x94af5000 dyld YY /usr/lib/system/libmathCommon.A.dylib at 0x94af5000 (offset -0x6b50b000) 8 libicucore.A.dylib - 0x97cf4000 dyld YY /usr/lib/libicucore.A.dylib at 0x97cf4000 (offset -0x6830c000) 9 libobjc.A.dylib - 0x926f0000 dyld YY /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 YY /usr/lib/libauto.dylib at 0x95eac000 (offset -0x6a154000) 11 libstdc++.6.0.4.dylib - 0x97e3d000 dyld YY /usr/lib/libstdc++.6.0.4.dylib at 0x97e3d000 (offset -0x681c3000) 12 _mesh_oned.so - 0x1000000 dyld YY /Users/sethrj/_code/_build/pytrt-gcc45DEBUG/meshlib/swig/_mesh_oned.so at 0x1000000 (offset 0x1000000) 13 libhdf5.7.dylib - 0x122c000 dyld YY /opt/local/lib/libhdf5.7.dylib at 0x122c000 (offset 0x122c000) 14 libz.1.2.5.dylib - 0x133000 dyld YY /opt/local/lib/libz.1.2.5.dylib at 0x133000 (offset 0x133000) 15 libstdc++.6.dylib - 0x600000 dyld YY /opt/local/lib/gcc45/libstdc++.6.dylib at 0x600000 (offset 0x600000) [snip] 

Tenga en cuenta que el error malloc se produce en la dirección de memoria del sistema libstdc++ , no en la que está vinculada la biblioteca compartida.

Intentos de resolución

Intenté forzar a los MacPorts a construir Python utilizando GCC 4.5 en lugar del comstackdor de Apple, pero la fase de instalación falla porque necesita crear un “Framework” para Mac, algo que el GCC de vainilla aparentemente no funciona.

Incluso con el indicador del comstackdor -static -static-libstdc++ , __ostream_insert llama a std::basic_streambuf desde la biblioteca compartida cargada por el sistema.

Intenté modificar DYLD_LIBRARY_PATH al anteponer /opt/local/lib/gcc45/ pero sin resultado.

¿Qué puedo hacer para que esto funcione? Estoy al final de mi ingenio.

Más información

Este problema parece ser común para mac os x . Observe cómo en todas las salidas de depuración se muestra, la dirección salta entre las llamadas a std::__ostream_insert y std::basic_streambuf::xsputn : está dejando el nuevo código GCC 4.5 y saltando al código de biblioteca compartida más antiguo en /usr/bin . Ahora, para encontrar una solución …

Resuelto. Descubrí que este problema no es tan infrecuente al mezclar versiones de GCC en la mac. Después de leer esta solución para mpich y verificar el código fuente de mpich , encontré que la solución es agregar la siguiente bandera a gcc en sistemas mac:

 -flat_namespace 

Estoy tan feliz. Ojalá esto no me hubiera tomado una semana para averiguarlo. 🙂

Ejecute Python en GDB, establezca un punto de interrupción en malloc_error_break . Eso te mostrará qué se está liberando y que no se ha asignado. Dudo que esto sea un error entre ABIs entre las versiones de libstdc ++.