C++ 菜鸟的补习:.h,.cpp,.a,.so,静态链接,动态链接,加载之概览

2,807 阅读2分钟

早就该补的缺课。。。很多内容来自 《深入理解计算机系统》 第七章

真是本好书,推荐大家都要看看。这里写的仅仅是一点点【概览】,停留于皮毛,日后还需要再深入研究。

.h 到底是啥,和 .cpp 毛关系?编译咋用?

对于一个稍稍大和复杂一丢丢的软件而言,我们通常会将声明写在 .h 中,然后在 .cpp 中进行实现。

无论我们的 .h 怎么写,我们要用它的时候,都是将它 include 进 cpp 的最顶端。

被 include 的东西会怎样?会在预处理的时候被直接拷贝到 include 的位置。

这岂不是和我们直接把声明写在 cpp 里面一样了?

是啊就是这样的 qwq ,只不过中间插入了一步预处理。

至此,.h 使命完成,后面没他啥事了。

你说的这个目标文件,到底是什么样的东西?

目标文件,ObjectFIle

其实有好几类目标文件,.o、.so、.out 其实都是。

.o:Object 可重定位目标文件

其包含二进制代码、数据,可以和其他可重定位目标文件合并,生成一个可执行目标文件

.out(或者没有后缀名):可执行目标文件

其包含二进制代码、数据,可以直接复制到内存执行

.so SharedObject ,也叫动态链接库

so 是一种特殊的可重定位目标文件,其可以在加载/运行时被动态加载进内存并链接

.a,静态链接库

静态链接器工作方式

  1. Symbol Resolution(符号解析):将每个 symbol 的引用定义关联起来
  2. 重定位:ccl、as 生成从地址 0 开始的代码、数据节(Section),ld 需要将每个符号的定义与一个内存位置相关联,从而重定位这些 section。最后再修改引用,让符号定义指向这个内存的位置。

.so,动态链接库

这里需要注意:动态链接器 ld-linux.so 本身也是一个 so。与静态链接生成的二进制可执行文件不同,加载器加载程序后不会直接把控制交给程序,而是加载并运行了这个动态链接器。动态链接器的运行大致如下:

  1. 重定位各个 so 的文本、数据到某两个内存段;
  2. 重定位 foo 中的所有对 libc.so、libfooFunc.so 的定义符号的引用
  3. 最后,ld 将控制权转移给 foo。从此开始,foo 的位置就固定下来了,而且在整个执行的过程中都不会发生改变。