总结extern “C”时引发的血案——c++的“编译、链接”原理与过程

本文深入探讨C++的编译和链接过程,解释了从源代码到可执行文件的转换步骤,以及extern "C"在多文件编译中的作用。详细阐述了链接器的工作原理,包括静态库的处理方式和解决链接错误的策略,特别是针对LNK2005和LNK1169错误的分析。同时,介绍了编译器选项如/ML、/MT对C++标准库的影响,以及如何避免版本不一致导致的问题。
摘要由CSDN通过智能技术生成

从C/C++源程序到可执行文件要经历两个阶段:(1)编译器将源文件编译成汇编代码,然后由汇编器(assembler)翻译成机器代码(再加上其它相关信息)后输出到一个个目标文件(object file,VC的编译器编译出的目标文件默认的后缀名是.obj)中;(2)链接器(linker)将一个个的目标文件(或许还会有若干系统库)链接在一起生成一个完整的可执行文件。

C语言提供了一种将多个目标文件打包成一个文件的机制,这就是静态链接库(static library)。开发者在链接时只需指定程序库的文件名,链接器就会自动到程序库中寻找那些应用程序确实用到的目标模块,并把(且只把)它们从库中拷贝出来参与构建可执行文件。

链接器按照所有目标文件和库文件出现在命令行中的顺序从左至右依次扫描它们,在此期间它要维护若干个集合:(1)集合E是将被合并到一起组成可执行文件的所有目标文件集合;(2)集合U是未解析符号(unresolved symbols,比如已经被引用但是还未被定义的符号)的集合;(3)集合D是所有之前已被加入到E的目标文件定义的符号集合。一开始,E、U、D都是空的(注意:U和D集合存储的是符号(变量的名称,函数的名称等),不是变量的定义,或者函数的定义)

(1): 对命令行中的每一个输入文件f,链接器确定它是目标文件还是库文件,如果它是目标文件,就把f加入到E,并把f中未解析的符号和已定义的符号分别加入到U、D集合中,然后处理下一个输入文件。

(2): 如果f是一个库文件,链接器会尝试把U中的所有未解析符号与f中各目标模块(因为库文件往往是多个obj文件打包起来的,例如静态库文件a.lib是 1.obj和2.obj的合并。1.obj和2.obj就是目标模块,a.lib就是一个库文件)定义的符号进行匹配。如果某个目标模块m定义了一个U中的未解析符号,那么就把m加入到E中,并把m中未解析的符号和已定义的符号分别加入到U、D集合中。不断地对f中的所有目标模块重复这个过程直至到达一个不动点(fixed point),此时U和D不再变化。而那些未加入到E中的f里的目标模块就被简单地丢弃,链接器继续处理下一输入文件。

(3): 如果处理过程中往D加入一个已存在的符号(即redefinition symbols ***错误),,或者当扫描完所有输入文件时U非空(即unresolved symbols ***错误),链接器报错并停止动作。否则,它把E中的所有目标文件合并在一起生成可执行文件。

VC带的编译器名字叫cl.exe,它有这么几个与系统库有关的选项: /ML、/MLd、/MT、/MTd、/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值