temp

来源:互联网 发布:美国全球的盟友网络 编辑:程序博客网 时间:2024/05/21 10:57
编译器编译源代码后生成的文件叫做目标文件。

目标文件就是源代码编译后但未进行链接的那些中间文件(Windows的.obj和Linux下的.o),它跟可执行文件的内容与结构很相似,所以一般跟可执行文件格式一起采用一种格式存储。 

#include <stdio.h> 


void foo() 

   printf("%s","I am from mylib!\n"); 



用 


cl /c /MLd mylib.c 


( ML 要是大写的,否则不认。) 


命令编译,注意 /MLd 选项是指定 libcd.lib 为默认标准库。 lib.exe 是 VC 自带的用于将目标文件打包成程序库的命令,所以我们可以用 


lib /OUT:my.lib mylib.obj 


将 mylib.obj 打包成库,输出的库文件名是 my.lib 。接下来把 main.c 改成 : 


/* main.c */ 


void foo(); 


int main() 

   foo(); 
   return 0; 



用 


cl /c main.c 


编译,然后用 


link main.obj my.lib 








    一开始 E 、 U 、 D 都是空集,链接器首先扫描到 main.obj ,把它加入 E 集合,同时把未解析的 foo 加入 U ,把 main 加入 D ,而且因为 main.obj 的默认标准库是 libc.lib ,所以它被加入到当前输入文件列表的末尾。

接着扫描 my.lib ,因为这是个库,所以会拿当前 U 中的所有符号 ( 当然现在就一个 foo) 与 my.lib 中的所有目标模块 ( 当然也只有一个 mylib.obj) 依次匹配,看是否有模块定义了 U 中的符号。

结果 mylib.obj 确实定义了 foo ,于是它被加入到 E , foo 从 U 转移到 D , mylib.obj 引用的 printf 加入到 U ,同样地, mylib.obj 指定的默认标准库是 libcd.lib ,它也被加到当前输入文件列表的末尾 ( 在 libc.lib 的后面 ) 。

不断地在 my.lib 库的各模块上进行迭代以匹配 U 中的符号,直到 U 、 D 都不再变化。很明显,现在就已经到达了这么一个不动点,所以接着扫描下一个输入文件,就是 libc.lib 。

链接器发现 libc.lib 里的 printf.obj 里定义有 printf ,于是 printf 从 U 移到 D ,而 printf.obj 被加入到 E ,它定义的所有符号加入到 D ,它里头的未解析符号加入到 U 。

链接器还会把每个程序都要用到的一些初始化操作所在的目标模块 ( 比如 crt0.obj 等 ) 及它们所引用的模块 ( 比如 malloc.obj 、 free.obj 等 ) 自动加入到 E 中,并更新 U 和 D 以反应这个变化。

事实上,标准库各目标模块里的未解析符号都可以在库内其它模块中找到定义,因此当链接器处理完 libc.lib 时, U 一定是空的。最后处理 libcd.lib ,因为此时 U 已经为空,

所以链接器会抛弃它里面的所有目标模块从而结束扫描,然后合并 E 中的目标模块并输出可执行文件。 

原创粉丝点击