链接时库文件没有放在命令行尾部所造成的问题

1、今天在用gcc命令编译使用了动态链接库中的函数的源码时,出现了问题,如下:

需要说明下所有提示未定义的函数都是在动态库libitcastsocket.so和libmessagereal.so这两个动态库之中的,这些函数是在MngClient_Agree中使用的。上面三个.o文件是根据源文件编译好的,都没有问题。然后我使用以下命令想将三个.o的文件链接成可执行目标文件。

gcc -L/home/project/day01/SecMngSever_SecMngClient_linux/lib  -lpthread -litcastsocket -lmessagereal keymngclient.o keymnglog.o keymngclientop.o -o keymngclient

上面的命令,我仔细检查了所用的动态库的路径和动态库名,都没有错误。但是还是出现了上图中的未定义错误。按道理来说,动态库都能找到,链接的时候是能够对使用的动态库函数完成符号解析的。可为什么会出错呢?最后发现原来是使用gcc命令的时候,把指定动态库放在了.o文件之前导致的。把指定动态库放到后面就行了,如下:

gcc -L/home/project/day01/SecMngSever_SecMngClient_linux/lib keymngclient.o keymnglog.o keymngclientop.o -lpthread -litcastsocket -lmessagereal  -o keymngclient

2、将库文件放在前面出现未定义的原因:linux链接器在符号解析阶段是按照从左向右的顺序扫描命令行的。当动态库没有放在命令行的尾部时,可能出现先扫描动态库,后扫描源文件的情况。这时候在后扫描源文件的时候就不会检查前面的动态库是否定义了该源文件使用过的符号,从而导致出现未定义的错误。就上面的例子来说,就是keymngclientop.o中的MngClient_Agree函数中使用了动态库libmessagereal.so和libitcastsocket.so的函数,而链接的时候将keymngclientop.o放在了在这两个动态库之后,那么最后解析keymngclientop.o中的符号时,就会发现率属于动态库libmessagereal.so和libitcastsocket.so的函数没有定义,因为不会搜索前面的文件是否有符号的定义。所以一般都是将库放在命令行的末尾。

3、linux链接静态库的方法:

    

 

4、动态链接库的使用:

       从3中我们可以知道,静态链接库编译的时侯会链接到可执行文件之中。而动态链接库不会链接到可执行文件之中,所以编译之后是部分链接的可执行目标文件。在部分链接的时候需要指定链接的动态库的路径和动态库名,虽然不链接进可执行目标文件,但是需要从动态库中查找可重定位目标文件中的外部符号,从而保证整个编译过程通过。对应于图中的1。

     对于图中的2,加载器加载和执行了prog21之后,发现在可执行文件的.interp节包含了动态链接器的路径名,从而加载和运行这个动态链接器。此时,动态链接器会执行下面的重定位完成链接任务。

  •     重定位libc.so的文本和数据到内存段。
  •     重定位libvector.so的文本和数据到另一个内存段。
  •      重定位prog21中所有对libc.so和libvector.so定义的符号的引用

 

总结来说就是,对于动态库,静态链接阶段只完成对动态库的符号解析(图中1),从而将引用的动态库中的全局符号保存在符号表中。而重定位是在运行部分链接可执行目标文件的时候调用动态链接器完成的(图中2)。

这里需要说一下,对于linux的动态链接器ld-linux.so查找可执行文件的过程:

对于elf格式的可执行文件,是由动态链接器ld-linux.so来完成可执行文件内部使用的库文件的调用操作的。ld-linux.so需要知道所调用的库文件所在的路径,一般会先搜索可执行文件内部的DT_RPATH段(包含了可执行文件所调用库的路径),然后再搜索环境变量LD_LIBRARY_PATH(环境变量的值也是路径),再搜索/etc/ld.so.cache文件列表,最后搜索/lib、/usr/lib目录找到库文件载入内存。

可以使用ldd命令来查看ld-linux.so调用信息,如下:

如果使用ldd命令发现有动态库找不到,可以将动态库的路径添加到LD_LIBRARY_PATH中。

 

 

 

==》对于链接静态库和动态库可以参控《深入理解计算机系统》7.6.3节和7.10节。

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值