GCC/LD编译链接潜规则 (第一弹) : 当一个符号被多重定义时
来源:互联网 发布:淘宝鹊桥佣金 编辑:程序博客网 时间:2024/05/29 17:52
gcc/ld的编译链接的有很多潜规则, 如果不幸遇到了, 并且没有意识到这是个潜规则, 那么会浪费很久很久的调试时间而不得其解. 下面总结我所遇到的一些潜规则.
本文先出第一弹, 其他的潜规则将陆续放出.
潜规则:
当一个符号在多个目标文件(.o)里同时出现时, LD报错. 提示符号多重定义.
当一个符号在多个静态库(.a)里同时出现时, LD不报错, 以第一个遇到的为准. 并且不会有任何warning提示 !!! 这个潜规则可能导致很多意想不到的问题!!!
测试代码:
helper.h
helper1.cpp
helper2.cpp
symbol_in_multi_obj.cpp
编译命令:
测试结果:
链接.o文件失败, 提示符号重定义
链接.a文件成功. 但其实链接的是第一个.a中的符号
先链helper1.a, 输出 “call myfun in helper1.cpp”
先链helper2.a, 输出 “call myfun in helper2.cpp”
真实案例:
Shasha同学的cgi类中调用http_request_helper类发请求, 发现程序行为总是和预期的不一致, 后来排查发现, 在Makefile中有另外的依赖库(.a)中也打包了http_request_helper类, 但是类的实现比较老, 导致把后面的新库覆盖!而GCC/LD对此没有任何提醒!!! Shit.
附上perryyang同事的补充:
补充一些:
GCC/LD在
1.做符号解析时,会把找到的第一个定义的代码链接进来(已经找到了就不再考虑后续的)
2.做Object链接时(*.o文件),每一个目标文件要做reloc操作,找到的第一个定义优先处理,再遇到一个相同的定义,就报"multip-definition 错误",这个可以通过-Wl,'-z muldefs'来解决,
-z muldefs会让ld在遇到重复定义时候,只处理第一个定义。
在运行时刻,如果:
1.存在多个相同的动态库名,则根据ldconfig中配置的库查找路径,先找到哪个就用哪个。如果机器中存在不同版本的动态库,则可能会用上错误的库,而从我们的代码中是检查不出错误的,
只能优先做"ldconfig -p | grep 库名"的检查,干掉一个不用的库就可以。
2.如果多个不同的动态库,拥有相同的全局变量名,则最后加载的动态库中的全局变量会冲掉之前加载的全局变量,导致结果异常(程序正常工作)
下面这篇文章对链接处理的说明的比喻挺贴切的:
http://webpages.charter.net/ppluzhnikov/linker.html
和VC++对比
另外, 对比VC++的行为, 是不一样的, VC++在发现多个依赖库中有同名符号时, 会符号重定义, 而不是默认的选择一个. 同时, VC++还提供了当符号重定义时忽略指定的库的能力.
- GCC/LD编译链接潜规则 (第一弹) : 当一个符号被多重定义时
- GCC/LD编译链接潜规则
- GCC/LD编译链接潜规则 (第三弹) : 当项目库中包含多个同名的头文件时.
- GCC/LD编译链接潜规则 (第二弹) : 为什么总链接失败? --LD对依赖库的输入顺序敏感
- GCC/LD编译链接潜规则 (第五弹) : 为什么会有undified symbol?
- GCC/LD编译链接潜规则 (第五弹) : 为什么会有undified symbol?
- GCC/LD编译链接潜规则 (第四弹) : ld 会把所有通过-l指定的动态库全部链接进最终的目标程序中, 无论是否真的用到(导致生产环境加载失败)
- 使用opencv和MFC中的类编译时找到一个或多个多重定义的符号解决方案
- VC编译错误:一个或多个多重定义的符号
- gcc编译,ld连接
- gcc编译,ld连接
- 使用vs编译出现 ”error LNK1169: 找到一个或多个多重定义的符号“的错误
- 关于链接过程中出现的“找到一个或多个多重定义的符号”和“无法解析的外部符号”错误的探究
- 找到一个或多个多重定义的符号解决方案
- 找到一个或多个多重定义的符号
- 编译链接5大潜规则
- Linux ubuntu 14.04 x86_64平台 gcc编译错误 Error: unsupported instruction `mov' 及ld链接错误
- gcc 编译文件时创建符号表
- Linux 0.12 OS. math - mul.c
- Java集合介绍1
- c++ 程序 有关移动文件
- cocos2d-x+Lua下getChildByTag返回不正确的解决方法
- 自动判断TextBox和CmoboBox是否为空(遍历控件)
- GCC/LD编译链接潜规则 (第一弹) : 当一个符号被多重定义时
- Reviewboard的中文乱码问题
- 使用Hibernate向mysql数据库中插入中文,数据库中显示??乱码
- 集群文件系统 moosefs 安装配置 容灾恢复
- IT职场求生法则(3)- 部门经理及副总适用法则
- uva10066 - The Twin Towers(dp,lcs)
- SpringMVC源码剖析(三)- DispatcherServlet的初始化流程
- sencha route实现浏览器及Android返回按钮页面返回
- 汉诺塔 Hanoi 递归实现