写好代码到生成可执行程序之间发生了什么
1.预编译
hello.c->hello.i, 去除宏,#include等带“#”的预编译指令和注释
2.编译
hello.i->hello.s 进行语法分析,优化等操作后生成对应的汇编代码
3.汇编
hello.s->hello.o 将汇编查表翻译成机器指令
4.链接
链接一些.o文件(.o也就是object文件,中间目标文件,简称目标文件),生成最后的可执行文件
链接
链接的作用
定义在其它模块的全局变量和函数在最终运行时的绝对地址都要在最终链接的时候才能确定,所以编译器要将源代码文件编译成一个未链接的目标文件,然后由链接器最终将目标文件链接起来形成可执行文件
链接可以实现模块之间的通信(模块间函数调用,模块间的变量访问),使得各个模块可以独立编译再组装起来
链接的主要内容就是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接,主要就是把一些指令对其它符号地址的引用加以修正(地址和空间分配,符号决议,重定位),比如在编译main.c的时候,用到了其它地方的foo函数,还不知道foo的地址,就先搁置,等链接的时候再填入正确的foo函数地址。
动态连接
静态链接的问题
1.每个程序内部保留了像printf()函数,scanf函数等公用库函数,还有其他函数和辅助数据结构,即使是公用的库也会被拷贝多份,造成内存浪费
2.更新一个小库,用到这个库的其它.o都要更新
动态链接(.so, .dll)
就是将链接过程推迟到运行时再进行,公用库只加载一份;如果要更新,那么只要将要更新的库替换,其它不用动(静态链接
需要对其它重新进行链接)
小细节
在将hello.o链接生成hello可执行程序时,也需要用到lib.so,但实际上不会真的将lib.so链接进去(运行时链接);这里用到lib.so是
为了用到lib.so里的符号信息,这样可以知道哪些函数是动态符号,完成链接