代码之家  ›  专栏  ›  技术社区  ›  mbudisic

动态链接库-生成可执行文件时成功,生成另一个时相同的安装程序失败。因此

  •  1
  • mbudisic  · 技术社区  · 16 年前

    我正在编写一个数字代码,在其中我想使用第三方编写的共享库。我正在研究一个x86 K8架构,在CentOS的领导下。我希望构建的目标是一个python或一个matlab扩展模块,据我所知,gcc构建了动态链接的共享库,内置了额外的matlab/python脚手架。在这里,我将重点介绍Python,因为同样的问题也会发生,而且它可能对社区更为熟悉。

    库开发人员最初提供了动态库和一些用C++编写的测试代码。他打算这样分发他的图书馆。我应该注意到,我正在尽可能少地为原始开发人员增加负担,因为库可能在一段时间前就已经是他的一个辅助项目了,他的测试代码最终工作正常。因此,我正在尽我所能最大限度地解决我这方面的问题。我设法将他的示例构建成可执行文件,只使用GCC4.5.0。我使用的普通gcc版本,4.1.2,在链接过程中产生了四个“未定义的引用”错误(使用g++),特别是 _M_insert<long>(long) , _M_widen_init() , _M_insert<double>(double) 和 __ostream_insert<char, std::char_traits<char> > . 这些都是 std 命名空间。使用G++4.5.0编译解决了这些未定义的引用,并且示例可执行文件运行正常。根据E.R.的意见, readelf -x.comment libmaxent_k8.so ,表示原始库是用gcc 4.4.1构建的。

    为了测试链接到Python扩展是否有效,我在C++中构建了一个小的Python扩展函数,只添加了两个数字。具体来说,它不使用任何我想使用的库中的内容。接口是用G++4.50编译而成的swig 2.0。代码在python 2.4.3中运行良好。但是,当我尝试链接到原始库时,在不引用其中的任何符号的情况下,代码再次链接良好,但是在运行时,在导入扩展时,我得到 ImportError: libmaxent_k8.so: undefined symbol: _ZNSo9_M_insertIlEERSoT_ ,通过 c++filt 是 _M_insert(long) 这是原始代码之一,当C++代码使用G+4.1.2链接时,它是未定义的。

    我怀疑问题出在链接和运行python期间libstdc++版本不匹配,但我不知道如何解决这个问题。对于我来说,最好的情况是,当链接扩展时,在没有GCC4.5.0的情况下,可以让我从中解脱出来,也许我在解决最初的4个缺少引用的问题时是在向前跳。Bing是否可以通过静态链接libstdc++6.0.14(这是gcc 4.5.0的一部分)来解决这个问题,同时仍然保留动态链接库的特性?尽管,Python与GCC4.5.0没有合作的问题,但Matlab有,他们的支持声称可靠性仅高达GCC4.2.0。因此,我希望尽可能少地使用4.5.0进行编译。我的gcc附带了6.0.8版本的libstdc++。

    这里有一些关于图书馆的报告。请记住,尽管有所有这些引用,但当直接编译到可执行文件时,代码仍然有效。

    $ readelf -aD /home/mbudisic/lib64/libmaxent_k8.so | grep NEEDED
    0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
    0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
    
    $ ldd -d libmaxent_k8.so 
    undefined symbol: _ZSt4cerr (./libmaxent_k8.so)
    undefined symbol: _ZNSt8ios_base4InitD1Ev   (./libmaxent_k8.so)
    undefined symbol: _ZSt4cout (./libmaxent_k8.so)
    undefined symbol: __gxx_personality_v0  (./libmaxent_k8.so)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b92457f3000)
        libc.so.6 => /lib64/libc.so.6 (0x00002b9245a01000)
        /lib64/ld-linux-x86-64.so.2 (0x000000366e200000)
    

    运行 nm -uC libmaxent_k8.so 结果来自libm和libstdc++库的35个“u”标记的符号和两个“w”标记的符号,这远远超过了在链接/运行中报告为未定义的。

    2 回复  |  直到 16 年前
        1
  •  2
  •   Employed Russian    16 年前

    一般来说,glibc和libstdc++试图提供向后兼容性——在较旧的系统(或使用较旧的gcc)上构建的二进制文件继续在较新的系统上运行。

    相反,在glibc-2.5系统上运行与glibc-2.10链接的二进制文件,或者运行用gcc-4.4构建的针对gcc-4.2附带的libstdc++的二进制文件是一个非目标。

    因此,您必须要求使用希望支持的最旧gcc(在您的情况下是4.2)构建二进制文件,或者安排使用新的libstdc++(通过修改 LD_LIBRARY_PATH ,或通过使用 LD_PRELOAD )对于matlab和python。

    glibc的向后兼容性非常好,但是libstdc++的记录比较零乱;因此matlab声称只有libstdc++.so.6.0.8是稳定的,并且支持它可能是正确的。你只要试试就行了,因为 libmaxent_k8.so 使用GCC-4.2构建)您没有任何其他选项(我可以想到)。

        2
  •  1
  •   m1tk4    16 年前

    下面是一篇很好的文章,说明为什么静态链接libstc++可能不是一个好主意:

    http://www.trilithium.com/johan/2005/06/static-libstdc/