动态库链接踩坑记

问题

最近,在一系列的编写代码、编译、正确的形成可执行文件后,将可执行文件运行在生成环境时,出现了应该是在编译链接时最常见的错误:Symbol not defined。下面,将会逐一的从问题是如何产生,以及如何解决进行说明,就当做是自我的一个问题记录。

原因

对于生产环境出现问题的可执行文件A,执行命令 nm A 发现的确存在着报错的时候的函数有着标志U(表明该函数未定义),可此函数在可执行文件A中并没有任何的声明,这只能说明,该函数是来自于第三方的库文件,经过检查发现,的确存在了一个动态库文件中使用了此函数。同样的使用命令 nm A 查看发现该函数同样在该动态库中未定义。
起初,我们认为是别人提供的这个动态库.so不正确,因此,我们重新编译了这个动态库后,再重新放入生成环境,再次执行,同样的错误继续出现。这时候,很自然而然的我们怀疑到了应该是编译动态库的make文件出现了错误。
在仔细认真的检查后make文件后,发现在编译形成动态库时,其最终形成目标集的命令类似下面的命令

> gcc -shared -fPIC libxxx.a xxxx.o -o libxxxx.so
如果认真的看,会发现该动态库还链接了一个其他的静态库,而那个未定义符号函数正是在这个静态库中声明定义的。很明显,在编译动态库的时候,由于采用gcc的编译器的版本查找符号是从前向后进行查找,而.o文件引用了前面.a文件,因此,.o文件 并没有真正的链接到正确的函数符号。而在这个过程中,也并没有报告错误,而是顺利的产生了动态库文件,这也就间接的导致了上述问题的发生。

解决

在gcc编译动态库的时候,即使出现了符号未正确的链接的情况,链接器也只是跳过该错误进行执行,这是由于gcc为了某种原因允许了这种情况(具体的原因,大家可以上网查阅,在此就不赘述了),因此,gcc编译器提供了下面的一些参数用于告知链接器对此种情况进行错误报告(很多的类似参数,区别建议大家去查阅gcc的编译手册)

-Wl,–no-undefined
-Wl,–unresolved-symbols=ignore-in-shared-libs
至此,解决上述的问题,我们可以将静态库文件和目标文件换个位置便可解决,但是我们还是建议大家在编译动态库的时候加入上述的参数,避免此类问题的出现。

总结

对于一个后端工程师来说,编译、链接、ELF文件是一项必不可少的知识,这里给出一些常用的命令,这些命令都可以帮助大家在碰到此类问题时候不会两眼一抹黑。具体的用法,去man一下吧。

ldd –查看可执行文件链接那些动态库
nm –查看可执行文件,库文件符号表
readelf –查看elf文件的文件信息
objdump –显示目标文件的信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值