1、目标文件的生成:
由编译器针对源文件编译生成,生成的.o或者.so(动态库)或者.a(静态库)也可以看作是目标文件;
2、静态库的生成:
由给定的一堆目标文件以及链接选项,链接器可以生成两种库,分别是静态库以及动态库;
3、静态链接指定是哪个阶段/过程?
静态链接是指将多个目标文件链接在一起以创建可执行文件(该可执行文件用到了静态库)或静态库的过程。
4、当使用静态库作为目标文件进行链接时(这个过程叫做静态链接),链接器做了什么?
当你使用静态库进行静态链接时,链接器只取静态库中被使用到的目标文件,而静态库中没被使用的目标文件不会进行链接。然后将它们与你的程序的其他目标文件一起链接到最终的可执行文件中。
5、将静态库链接到动态库时,链接器做了什么?有什么影响?
1)链接器做了什么:
静态库链接到动态库时,链接器会执行静态链接,即将这个静态库中被使用到的代码完全复制到生成的动态库中。
2)有什么影响:
- 如果多个动态库都链接了同一个静态库,每个动态库都会包含一份该静态库的拷贝。会导致内存浪费;
- 可能存在一致性问题,即动态库A拷贝了静态库M的版本1;动态库B拷贝了静态库M的版本2,而静态库M的版本1与版本2对同一个函数做了修改,这样可执行文件运行时调用版本1还是版本2的函数是不确定的。
3)建议:
将静态库链接到动态库中不是一个常见或推荐的做法,因为它可能引发一系列问题。如果有必要共享代码,通常更好的做法是将代码放入动态库中。
6、由静态库引发的程序段错误案例
1)现象: 可执行文件E运行时,调用一个类C中的函数F后崩溃,提示段错误。
2)直接原因:分析后段错误的原因是野指针(调飞了),即找不到函数F的地址。
3)根本原因: 该类C定义在静态库M中,静态库M被静态链接到动态库A与动态库B中,动态库A与B又被链接到可执行文件E中。而动态库A与B是分别在不同时间编译的。A与B编译期间一个coder修改了静态库M中类C的内容,导致A与B用到的静态库M不同/类C不同/函数F地址不同(即类C的声明所在的头文件H未对齐),即遇到了【5】中提到的一致性问题。
4)段错误出现的流程:可执行文件E运行时,按照动态库A中包含的M中的头文件H查找函数F的内存地址并调用,而可执行文件E加载了动态库B中包含的M中函数F所在的头文件H的声明与实现。因此出现了地址错位,因此该指针为野指针,导致段错误。
7、参考资料:
1)彻底理解链接器:三,库与可执行文件