这里总结下工作中遇到的链接问题,大致有以下几种:
- 找不到符号undefined reference
- 用的别的库里面的符号
众所周知,编译的时候,头文件里面有符号就行,然后会在链接的时候去库的符号表里面去找,找符号这个过程,会先根据当前用的c还是c++、哪个c++版本来确定用哪个名称改编算法,然后根据这个算法计算的符号名称来查找。
很显然,出现找不到符号的原因,有:
- 库用的c的名称改变算法生成的,但是头文件里面没有说明,这时候只需要在有文件里面加个extern "c"就行;
- 库是用的旧版的c++,但是查找是根据c++11来的,这时候就只能重新编译库了,换成用c++11或者是extern c;
用的别的库里面的符号是指链接先后顺序导致的,比如二进制程序依赖两个库a.so.2和b.so,但是b.so编译的时候是用的a.so.1,但是a.so.1和a.so.2里面的符号是一样的,内部出现的破坏性更新。如果这个程序先链接的a.so.2,再链接b.so,那么会出现这种情况:先用的a.so.2的符号A,放到了GOT里面,在b.so内部的代码在找符号A时,找到了a.so.2里面的实现,导致问题出现。
这个还可能出现一个问题,我在编译链接都没问题,但是运行的时候报:symbol lookup error,可以通过ldd查看二进制依赖的库,发现a.so库用的错误的库。这个是因为库目录的搜索顺序优先级导致,可以加个-Wl,-rpath
,优先搜索你指定的目录。
修复的方法也简单,在编译b.so时,将a.so.1换成静态库编进代码里面,然后改成弱符号,也就是控制最终产物的外部符号,推荐连接时的控制。