您的位置:首页 > 其它

关于链接的一些理解

2016-04-28 14:14 281 查看
对于链接,它是程序编译的一个环节。

绝大多数编译器都不是一个单一的庞大程序,而是由许多稍小的程序组成。这些单独程序通常包括:C预处理器、语法和语义检查器、代码生成器、汇编程序、优化器、链接器、还包括一个调用所有这些程序并向各个程序传递正确选项的编译器驱动器程序。



链接一般分为两种:静态链接和动态链接。如果函数库的一份拷贝是可执行文件的物理组成部分,则称为静态链接。如果可执行文件只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数库,则称为动态链接。

收集模块准备执行的三个阶段称为:链接编辑、载入、运行时链接。

静态链接的模块被链接编辑并载入以便运行。

动态链接的模块被链接编辑后载入,并在运行时进行链接以便运行。程序执行时,在main()函数被调用前,运行时载入器把共享的数据对象载入到进程的地址空间。外部函数被真正调用之前,运行时载入器并不解析它们。所以即使链接了函数库,如果并没有实际调用,也不会带来额外开销。

对于这两种链接形式,相对而言动态链接更好,它的优点是可执行文件的体积可以非常小,虽然运行速度稍慢,但动态链接能够更加有效地利用磁盘空间,而且编译链接阶段的时间也会缩短。

动态链接是一种”just-in-time”链接,意味着程序在运行时必须能够找到它们所需要的函数库。链接器通过把库文件名或路径名植入可执行文件中来做到这点,意味着函数库的路径不能随意移动。

使用静态链接一个潜在问题在于将来版本的操作系统可能与可执行文件所绑定的系统函数库不兼容。如果应用程序静态链接于版本N的操作系统中,当把程序运行于版本N+1的操作系统上,可能会出现崩溃情况或者不明显的错误。而如果应用程序动态链接到版本N的系统函数库,当它运行于版本N+1的操作系统上时,它就会正确选取N+1版本的系统函数库。

关于在UNIX下函数库链接总结几点:

1.动态库文件的扩展名是”.so”,而静态库文件的扩展名是”.a”

2.提供选项-lname,告知编译器链接到相应的name函数库

3.提供选项-Lpathname,告知编译器在指定的目录查找函数库。默认情况下,编译器会去/usr/lib下查找函数库,同时,系统中也存在环境变量LD_LIBRARY_PATH可用于指示查询函数库的目录

4.对于-lname函数库选项的使用,始终将其放在编译命令行的最右边。

对于第四点:

在动态链接中,所有的库符号进入输出文件的虚拟地址空间中,所有的符号对于链接在一起的所有文件都是可见的,相反,对于静态链接,在处理静态库(archive)时,它只是在静态库中查找载入器当时所知道的未定义符号。

简单而言,在编译器命令行中各个静态链接库出现的顺序非常重要,符号是通过从左到右的顺序进行解析的。

所以如果在自己的代码之前引入静态库,就会带来这样一个问题,因为此时尚未出现未定义的符号,所以它不会从函数库中提取任何符号。接着,当目标文件被链接器处理时,它所有的对函数库的引用都将是未实现的。

所以若像下面进行静态链接:

cc -lm main.c


则会出现一条错误信息,如下:

Undefined       first referenced
symbol          in file
sin             main.o
ld: fatal:  Symbol referencing errors. No output written to a.out


为了能从math库中提取所需的符号,首先需要让文件包含未解析的引用,如下:

cc main.c -lm
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: