




全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
今天编译遇到一个奇怪的问题, main.cpp 中有 main 函数,main.cpp 中需要用到 xxx 库 g+ -o main -lxxx main.cpp 这样编译不过,报错 main.cpp 中某行有 undefined reference(xxx 中的)。 把顺序调整一下: g+ -o main main.cpp -lxxx 能编过了. 原因是 gcc/g+ 编译是, 源文件不能在关联的库后面。 编译器从左到右扫描,需要两个表 A,B A:里面记录了所有没有被 resolve 的 symbol B: 里面记录了所有需要链接的库 一开始 A,B 两个表都是空的 从左到右扫描的时候的过程如下 1.如果是一个 obj 文件,则将不能被 resolve 的 symbol 加入到 A 表里面 2.如果是一个库文件,则查找其中是否有 A 表中的 symbol,如果有,则从 A 表中去掉该 symbol(因为 已经被当前库 resolve 了),同时将该库加入到 B 表中 扫描结束后如果 A 表非空,则会报错 现在的编译器默认都是进行一次扫描的,所以你需要将.o 文件放在前面,否则你这个 A 表直到最后才 生成,但这个时候所有的库已经扫描完了会造成 A 表非空 具体的可能会有些不一样,但是大体原理基本就是这样的。 摘录别人的分析: 1 gcc/g+链接时.o 文件以及库的顺序问题 1.1 写在前面 最近换了 xubuntu12.4,把原来的项目 co 出来编译的时候报“undefined reference to”。猜测是 gcc 的 版本问题,用-v 跟踪一下,发现 gcc-4.6 默认开 启了 ld 的as-needed 选项。关闭该选项(no-as- needed)后编译正常。深 入挖掘发现还是一个比较有意思的问题。 1.2 几个名词 gcc: 后面不特殊说明 gcc 代表 gcc/g+。 主程序块: 只包含 main 的 binary,可执行程序。 1.3 技术铺垫 1.3.1 编译动态库时的符号解析 有符号解析不了的时候,gcc 不会直接报错而是假设 load 的时候地址重定位修正。 1.3.2 linux 下查看一个可执行文件或动态库依赖哪些动态库的办法 你有一个 library 或者是可执行文件,你可以这样查看他的依赖关系: readelf -d ocamlocaml:$ readelf -d PyGalaxy.so Dynamic section at offset 0x7dd8 contains 26 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: libGalaxyParser.so . 0x000000000000000c (INIT) 0x18e0 0x000000000000000d (FINI) 0x6398 ldd 工具,如下: ocamlocaml:$ ldd PyGalaxy.so linux-vdso.so.1 = (0x00007fffc8ad3000) libGalaxyParser.so = /home/ocaml/lib/libGalaxyParser.so (0x00007f1736e6d000) . 1.3.3 load 动态库过程 基本的说就是符号重定位,然后合并到全局符号表。 1.4 gcc/g+链接时对库的顺序要求 先看看 gcc 手册对-L 和-l 的描述 -Ldir Add directory dir to the list of directories to be searched for -l. -llibrary -l library Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.) It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded. The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name. The directories searched include several standard system directories plus any that you specify with -L. Normally the files found this way are library filesarchive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with lib and .a and searches several directories. 基本的意思就是从左向右查找,如果是链接成动态库会稍微不同一点。 1.4.1 对于 library 的查找 查找需要连接的符号名是从前向后找,根据-L 指定的路径顺序查找;不同 目录下的同名的库,只取第 一个(从左向右),后面同名库被忽略; 1.4.2 对于符号的查找 从左向右查找,如果是主程序块和静态库,不能定位地址就报错: undefined reference to: xxx如果 是链接成动态库,则假设该符号在 load 的时候地址重定位。如果找不到对应的动态库,则会在 load 的时候报:“undefined symbol: xxx“这样的错误。 1.5 as-needed 对链接动态库的影响 先看看与动态库链接相关的几个选项的 man 说明: -as-needed -no-as-needed This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the -as-needed option. Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not. -as-needed causes a DT_NEEDED tag to only be emitted for a library that satisfies an undefined symbol reference from a regular object file or, if the library is not found in the DT_NEEDED lists of other libraries linked up to that point, an undefined symbol reference from another dynamic library. -no-as-needed restores the default behaviour. -add-needed -no-add-needed These two options have been deprecated because of the similarity of their names to the -as-needed and -no-as-needed options. They have been replaced by -copy-dt-needed-entries and -no- copy-dt-needed-entries. -copy-dt-needed-entries -no-copy-dt-needed-entries This option affects the treatment of dynamic libraries referred to by DT_NEEDED tags inside ELF dynamic libraries mentioned on the command line. Normally the linker wont add a DT_NEEDED tag to the output binary for each library mentioned in a DT_NEEDED tag in an input dynamic library. With -copy- dt-needed-entries specified on the command line however any dynamic libraries that follow it will have their DT_NEEDED entries added. The default behaviour can be restored with -no-copy-dt-needed-entries. This option also has an effect on the resolution of symbols in dynamic libraries. With -copy-dt-needed-entries dynamic libraries mentioned on the command line will be recursively searched, following their DT_NEEDED tags to other libraries, in order to resolve symbols required by the output binary. With the default setting however the searching of dynamic libraries that follow it will stop with the dynamic library itself. No DT_NEEDED links will be traversed to resolve symbols. 再看看 ld 的帮助 -add-needed Set DT_NEEDED tags for DT_NEEDED entries in following dynamic libs -no-add-needed Do not set DT_NEEDED tags for DT_NEEDED entries in following dynamic libs -as-needed Only set DT_NEEDED for following dynamic libs if used -no-as-needed Always set DT_NEEDED for following dynamic libs 关键的看as-needed ,意思是说:只给用到的动态库设置 DT_NEEDED。比如: g+ -shared PyGalaxy.o -lGalaxyParser -lxxx -lrt -o PyGalaxy.so 像这样链接一个 PyGalaxy.so 的时候,假设 PyGalaxy.so 里面用到了 libGalaxyParser.so 但是没 有用 到 libxxx.so。查看依赖关系如下: ocamlocaml:$ readelf -d PyGalaxy.so Dynamic section at offset 0x7dd8 contains 26 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: libGalaxyParser.so 0x0000000000000001 (NEEDED) Shared library: libxxx.so . 当开启as-needed 的时候,像 g+ -shared -Wl,-as-needed PyGalaxy.o -lGalaxyParser -lxxx -lrt -o PyGalaxy.so 这样链接 PyGalaxy.so 的时候,查看依赖关系如下: ocamlocaml:$ readelf -d PyGalaxy.so Dynamic section at offset 0x7dd8 contains 26 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: libGalaxyParser.so . as-needed 就是忽略链接时没有用到的动态库,只将用到的动态库 set NEEDED。 开启as-needed 的一些常见的问题: 1.5.1 链接主程序模块或者是静态库的时的undefined reference to: xxx g+ -Wl,-as-needed -lGalaxyRT -lc -lm -ldl -lpthread -L/home/ocaml/lib/ - lrt -o mutex mutex.o 假设 mutex 依赖 libGalaxyRT.so 中的东西。想想,因为 gcc 对库的顺序要求 和as-needed (因为 libGalaxyRT.so 在 mutex.o 的左边,所以 gcc 认为没有 用到它,as-needed 将其忽略),ld 忽略 libGalaxyRT.so,定位 mutex.o 的 符号的时候当然会找不到符号的定义!所以 undefined reference to 这个 错误是正常地! 正确的链接方式是: g+ -Wl,-as-needed mutex.o -lGalaxyRT -lc -lm -ldl -lpthread - L/home/ocaml/lib/ -lrt -o mutex 1.5.2 编译动态库(shared library)的时候会导致一个比较隐晦的错误 编译出来的动态库的时候没有问题,但是加载的时候有“undefined symbol: xxx”这样的错误。假如像这 也链接 PyGalaxy.so g+ -shared -Wl,-as-needed -lGalaxyParser -lc -lm -ldl -lpthread - L/home/ocaml/lib/ -lrt -o PyGalaxy.so PyGalaxy.o load PyGalaxy.so 的时候会有上面的运行时错误 ! 简单分析原因:因为 libGalaxyParser.so 在 mutex.o 的左边,所以 gcc 认为没 有用到它,as-needed 将其忽略。但是前面说的动态库符号解析的特点导 致 ld 认为某些符号是加载的时候才去地址重定位的。 但是 libGalaxyParser.so 已经被忽略了。所以就算
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 甘肃2025年西北师范大学招聘事业编制工作人员笔试历年参考题库附带答案详解
- 2025内蒙古阿拉善盟赛汗人力资源服务有限公司招聘10人笔试参考题库附带答案详解
- 鞍山职业技术学院《数字设计与验证技术》2023-2024学年第二学期期末试卷
- 昆玉职业技术学院《虚拟设计》2023-2024学年第二学期期末试卷
- 衡水职业技术学院《工程热力学与节能技术》2023-2024学年第二学期期末试卷
- 河北民族师范学院《CAD设计》2023-2024学年第二学期期末试卷
- 湖南信息学院《嵌入式系统设计与开发实践》2023-2024学年第二学期期末试卷
- 江苏工程职业技术学院《计算机视觉人脸图像合成与识别》2023-2024学年第二学期期末试卷
- 辽宁税务高等专科学校《中外管理思想比较》2023-2024学年第二学期期末试卷
- 厦门海洋职业技术学院《战术导弹工程与应用》2023-2024学年第二学期期末试卷
- 国企招标采购的合规性风险防控体系构建
- 人教A版高一下册必修第二册高中数学8.6.2直线与平面垂直【课件】
- 恋爱协议书违约合同
- 薪酬管理制度框架搭建
- 风湿免疫病患者结核病诊治及预防实践指南(2025版)解读课件
- 电梯日管控、周排查、月调度制度及管控清单(附记录表格)1
- 软件开发行业智能化软件开发方案
- 2025年全国中小学校学生禁毒知识竞赛题库及答案(共370题)
- 商铺装修管理规定
- 铁路心理测试题及答案
- T-HNCAA 061-2024 分布式光伏电站定期检查与性能评估技术标准
评论
0/150
提交评论