函数库、链接和载入
绝大多数编译器并不是一个单一的庞大程序。通常由多大67个稍小的策划年供需组成。这些程序再由一个叫做“编译器驱动器”的控制程序来调用。
静态链接(传统的可执行文件生成):
可执行文件并不能直接执行,需要载入到链接器。链接器把需要使用的每个库函数机器指令的一份拷贝加到生成的最终的可执行文件里。
动态链接
正如上面所说。如果函数库的一份拷贝是可执行文件的物理组成部分,那么我们称之为静态链接;如果可执行文件只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数(函数的机器指令),那么我们称之为动态链接。
不调用也不产生额外开销
动态链接:在运行时进行链接以便运行,但外部函数在被真正调用之前,运行时载入器并不解析他们。所以即使链接了函数库,如果并没有实际调用,也不会再来额外开销。
动态链接的优点
最好只使用动态链接
使用静态链接最大的危险是将来版本的操作系统可能与可执行文件绑定的系统函数库不兼容,我们无法保证早期版本的系统函数库能够在后期版本的系统上正确运行。
之前编译链接出的可执行文件(机器指令)在新的系统上不能起作用。因为旧的函数边一处的机器指令在以前版本的操作系统刚好是做那一件事,而在新的系统上就是做其他的事了。
而且有些函数库只能以动态链接的形式使用。因为为了规避上述所说的问题,最好的策略就是所有的应用都使用动态链接。
函数链接的5个特殊秘密
1、动态库文件的扩展名是".so",而静态库文件的扩展名是".a";
2、例如通过-lthread选项,是告诉编译链接到libthread.so;
3、编译器期望在确定的目录找到库;如果没哟用-Lhe -R选项,默认会去/usr/lib等几个目录下找;
4、不知道你的程序会使用哪些函数库时,可以通过观察包含什么头文件。例如math.h就提示你应该会用到math函数库。
5、与提取动态库的符号相比,静态库的符号提取的方法限制更严
小启发:始终将-l函数库选项放在编译命令行的最右边
警惕编写与库函数同名的函数以取代该库函数的行为(Interpositioning)
为了避免你自己声明的取代某个库函数的函数被其他文件也适用(本来是想使用标准库函数)。最好的办法就是把你的函数声明为static,这样它的作用就局限在一个文件中了。
产生链接器报告文件
ld 的-m选项可以让链接器产生一个报告,这个报告里面包括了被interpose的符号的说明。
略