库文件依赖顺序

GCC在链接时对依赖库的顺序是敏感的,被依赖的库必须放在后面,比如liba.a依赖libb.a,必须写成liba.a libb.a,否则链接将出错。在库比较多依赖关系比较复杂或者相互依赖或者自己不清楚的情况下,可以使用下面的选项来强制GCC重复查找依赖库:

g++ -o tt tt.o -Xlinker "-(" -lws2_32 -lclsocketd -Xlinker "-)"

强符号和弱符号

在链接中,如果多个目标文件中含有相同名字的全局符号的定义,链接器是怎么进行处理的?这里就涉及到强符号和弱符号的问题,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号,强符号和弱符号都是针对定义来说的,不是针对符号的引用。链接器会按照如下规则处理重复定义的全局符号:

规则1:不允许强符号被多次定义,否则链接器报符号重定义错误。

规则2:如果一个符号在某个目标文件中是强符号,在其它文件中都是弱符号,那么选择强符号。

规则3:如果弱符号在所有目标文件中都是弱符号,那么选择占用空间最大的一个。

我们可以通过GCC的__atrribute__((weak))来定义任何一个强符号为弱符号,如:

__atrribute__((weak)) weak = 1;

链接时如果未找到某个符号的定义,链接器就会报符号未定义错误,这种被称为强引用。与之对应的还有一种弱引用,如果弱引用的符号未定义,链接器对该引用不报错。我们可以使用GCC中的__attribute__((weakref))这个关键字来声明对一个外部函数的引用为弱引用,如:

__attribute__((weakref)) void foo();

int main()

{

if (foo) foo();

}

这种弱符号和弱引用对库来说十分有用,比如库中定义的弱符号可以被用户定位的强符号所覆盖,从而使程序使用自定义版本的库函数;或者程序可以对某些扩展功能模块的引用定义为弱引用,如果我们去掉了某些功能模块,那么程序也可以正常链接,只是缺少了相应的功能,这使得程序功能更容易裁剪和组合。

全局符号介入

在动态链接中,链接器按照各个模块之间的依赖关系,对各个共享对象进行装载并且将它们的符号并入到全局符号表时,如果两个不同的模块定义了同一个符号,会出现什么结果呢?这个问题涉及到共享对象全局对象介入,即一个共享对象里面的全局对象会被另一个共享对象的同名全局符号覆盖。Linux下的动态链接器的处理规则是这样的:当一个符号需要被加入全局符号表时,如果相同的符号名已经存在,则后加入的符号被忽略。

共享库版本

Linux使用共享库版本的方法来解决共享库的兼容性问题,它规定共享库的文件命名规则如下:

libname.so.x.y.z

x表示主版本号,主版本号表示库的重大升级,不同主版本号之间是不兼容的。

y表示次版本号,次版本号表示库的增量升级,即新增一些新的接口符号,且保持原来的符号不变。在主版本号相同的情况下,高的此版本号的库向下兼容低的次版本号的库。

z表示发布版本号,发布版本号表示库的一些错误修正、性能改进等,并不添加任何新的接口,也不对接口进行更改。相同主版本号、次版本号的共享库之间完全兼容。

Linux采用一种叫做SO-NAME的命令机制来记录共享库的依赖关系。每个共享库都有一个对应的SO-NAME,这个SO-NAME即共享库的文件名去掉次版本号和发布版本号,保留主版本号。比如一个共享库叫做libfoo.so.2.6.1,那么它的SO-NAME就是libfoo.so.2。系统会为每个共享库在它所在的目录创建一个跟SO-NAME相同的并且指向它的软链接,这个软链接会指向目录中主版本号相同、次版本号和发布版本号最新的共享库。

在编译输出ELF文件时,将被依赖共享库的SO-NAME保存到.dynamic中,这样当动态链接器进行共享库依赖文件查找时,就会根据系统中各种共享目录中的 SO-NAME软链接自动定向到所兼容的最新版本的共享库。

GCC链接的几个注意点的更多相关文章

  1. gcc链接g++编译生成的静态库和动态库的makefile示例

    使用c++开发程序或者库时,将库提供给其他人使用. 然而使用者是使用c开发的程序,链接g++编译生成的库时,于链接gcc生成的库,有所不同. 首先是静态库,以链接g++编译生成的libmylib.a为 ...

  2. GCC链接库的一个坑:动态库存在却提示未定义动态库的函数

    背景 在GCC中已经指定链接库,然而编译时却提示动态库函数未定义! 测试出现的错误提示如下: [GMPY@13:48 tmp]$gcc -o test -L. -lmylib test.c /tmp/ ...

  3. Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别

    昨天在自己的CentOs7.1上写makefile的时候,发现在一个C程序在编译并链接一个已生成好的lib动态库的时候出错.链接命令大概是这样的: [root@typecodes tcpmsg]# g ...

  4. gcc链接非标准(non-standard)命名库

    标准命名库: -lnamespace 标准链接库以lib开头, 并以so/a结尾. example gcc test.c -o test -L. -lhello 非标准命名库: -l:libname ...

  5. GCC链接时库顺序问题

    GCC或G++在编译链接时,如果命令行中含有库,则要特别注意了.根据<C专家编程>5.3节中的提示,GCC在链接时对命令行时的处理顺序是从左到右.证据是GCC的MAN: -l librar ...

  6. 【图片+代码】:GCC 链接过程中的【重定位】过程分析

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  7. gcc链接参数--whole-archive的作用

    // a.h extern void foo(); // a.cpp #include <stdio.h> void foo() { printf("foo\n"); ...

  8. g++/gcc 链接头文件 库 PATH

    转自http://blog.csdn.net/kankan231/article/details/24243871 在Linux下编译链接或运行c/c++程序时可能会遇到找不到头文件,找不到库文件的错 ...

  9. gcc 链接非标准名称库

    一般库的标准名称是libxxx.so或者libxxx.a, 如果没有, 也可以搞个linkname出来, 那就可以直接用 "-lxxx" 来链接了, 但要是你想直接用realnam ...

随机推荐

  1. Vuejs(14)——在v-for中,利用index来对第一项添加class

    版权声明:出处http://blog.csdn.net/qq20004604 (1)在v-for中,利用index来对第一项添加class <a class="list-group-i ...

  2. bash编程-执行流程

    1.顺序执行 shell脚本按从上到下的顺序依次执行,除非使用了选择.循环等执行流程. 2.选择执行 2.1 if # 格式一 if 条件; then # 语句 fi # 格式二 if 条件; the ...

  3. SQL注入之重新认识

    i春秋作家:anyedt 原文来自:https://bbs.ichunqiu.com/thread-41701-1-1.html 引言 作为长期占据 OWASP Top 10 首位的注入,认识它掌握它 ...

  4. 开源播放器 ijkplayer (二) :ijkplayer倍速变调问题解决方案

    转载注明出处:http://www.cnblogs.com/renhui/p/6510872.html 之前使用IjkPlayer做播放器的使用的时候,在做倍速播放的时候,发现播放的声音音调明显变高了 ...

  5. 如何用impress.js写有逼格的ppt

    概述 这是我学习课程impress让你的内容"舞"起来而做的总结和练手. 你可以点这里在线预览我做的ppt 注意:等加载完了之后,点击空格键翻页! 简化模板 下面是一个简化的模板 ...

  6. Win10下音频设备无法播放音乐问题定位

    最近一直在调试音频设备,由于音频设备需要在不同的采样率下面转换,所以会经常导致我的win10无法播放和录音. 刚开始在网上搜了相关的知识,但是一直没找到有效的解决方案.后来,无奈之下,使用了微软的声音 ...

  7. Datatable数据转换成excel导出时 数值类型在EXCEL中为文本形式 无法进行统计

    功能背景 有地税上以及各企业的一个缴费情况的比对,基于两表进行匹配查看数据是否在合理范围内,对比对完成表进行数值导出. 2.问题描述 匹配和生成匹配结果导出已成功完成,但是在数值列导出后变成了文本形式 ...

  8. Mac下搭建react及bable

    1.安装node 下载: https://nodejs.org/en/download/ 测试--->返回版本号即为安装成功: $ node -v $ npm -v 2.安装全局create-r ...

  9. [EXP]Apache Spark - Unauthenticated Command Execution (Metasploit)

    ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://gith ...

  10. OSI七层模型和tcp/ip四层模型对比

    OSI 与TCP/IP 模型对比 OSI 协议层名称 TCP/IP 协议层名称 封装的单元 功能描述 TCP/IP协议 应用层(Application) 应用层(Application) 数据 应用程 ...