欢迎来到天天文库
浏览记录
ID:47388831
大小:79.50 KB
页数:26页
时间:2019-07-11
《alreadydefinedin.obj-符号已定义问题原理及其解决方法》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、''alreadydefinedin*.obj“符号已定义”问题原理及解决方案VC6如果想在stdafx.h中定义全局变量,由于该头文件会被include多次,所以,经常会出现以下经典的错误:alreadydefinedinStdAfx.obj。解决方法:把该变量的定义intg_flag放到stdafx.cpp中,然后在使用的地方extern一下。假如你在CAADlg.cpp中使用了该变量g_flag,那么就在CAADlg.cpp的首部,构造函数的定义之外,添加上externintg_flag;许多VisualC++的使用者都碰到过LNK2005:symbolalrea
2、dydefined和LNK1169:oneormoremultiplydefinedsymbolsfound这样的链接错误,而且通常是在使用第三方库时遇到的。对于这个问题,有的朋友可能不知其然,而有的朋友可能知其然却不知其所以然,那么本文就试图为大家彻底解开关于它的种种疑惑。 大家都知道,从C/C++源程序到可执行文件要经历两个阶段:(1)编译器将源文件编译成汇编代码,然后由汇编器(assembler)翻译成机器指令(再加上其它相关信息)后输出到一个个目标文件(objectfile,VC的编译器编译出的目标文件默认的后缀名是.obj)中;(2)链接器(linker)
3、将一个个的目标文件(或许还会有若干程序库)链接在一起生成一个完整的可执行文件。 编译器编译源文件时会把源文件的全局符号(global''symbol)分成强(strong)和弱(weak)两类传给汇编器,而随后汇编器则将强弱信息编码并保存在目标文件的符号表中。那么何谓强弱呢?编译器认为函数与初始化了的全局变量都是强符号,而未初始化的全局变量则成了弱符号。比如有这么个源文件:externinterrorno;intbuf[2]={1,2};int*p;intmain(){ return0;}其中main、buf是强符号,p是弱符号,而errorno则非强非弱,因为它
4、只是个外部变量的使用声明。 有了强弱符号的概念,链接器(Unix平台)就会按如下规则(参考[1],p549~p550)处理与选择被多次定义的全局符号:规则1:不允许强符号被多次定义(即不同的目标文件中不能有同名的强符号);规则2:如果一个符号在某个目标文件中是强符号,在其它文件中都是弱符号,那么选择强符号;规则3:如果一个符号在所有目标文件中都是弱符号,那么选择其中任意一个; ''虽然上述3条针对的是Unix平台的链接器,但据作者试验,至少VC6.0的linker也遵守这些规则。由此可知多个目标文件不能重复定义同名的函数与初始化了的全局变量,否则必然导致LNK2
5、005和LNK1169两种链接错误。可是,有的时候我们并没有在自己的程序中发现这样的重定义现象,却也遇到了此种链接错误,这又是何解?嗯,问题稍微有点儿复杂,容我慢慢道来。 众所周知,ANSIC/C++定义了相当多的标准函数,而它们又分布在许多不同的目标文件中,如果直接以目标文件的形式提供给程序员使用的话,就需要他们确切地知道哪个函数存在于哪个目标文件中,并且在链接时显式地指定目标文件名才能成功地生成可执行文件,显然这是一个巨大的负担。所以C语言提供了一种将多个目标文件打包成一个文件的机制,这就是静态程序库(staticlibrary)。开发者在链接时只需指定程序库的
6、文件名,链接器就会自动到程序库中寻找那些应用程序确实用到的目标模块,并把(且只把)它们从库中拷贝出来参与构建可执行文件。几乎所有的C/C++开发系统都会把标准函数打包成标准库提供给开发者使用(有不这么做的吗?)。 程序库为开发者带来了方便,但同时也是某些混乱的根源。我们来看看链接器(Unix平台)是如何解析(resolve)对程序库的引用的(参考[1],p556)。 在符号解析(symbolresolution)阶段,链接器按照所有目标文件和库文件出现在命令行中的顺序从左至右依次扫描它们,在此期间它要维护若干个集合:(1)集合E是将被合并到一起组成可执行文
7、件的所有目标文件集合;(2)集合D是所有之前已被加入E的目标文件定义的符号集合;(3)集合U是未解析符号(unresolvedsymbols,即那些被E中目标文件引用过但在D中还不存在的符号)的集合。一开始,E、D、U都是空的。(1):''对命令行中的每一个输入文件f,链接器确定它是目标文件还是库文件,如果它是目标文件,就把f加入到E,并把f中未解析的符号和已定义的符号分别加入到U、D集合中,然后处理下一个输入文件。(2):如果f是一个库文件,链接器会尝试把U中的所有未解析符号与f中各目标模块定义的符号进行匹配。如果某个目标模块m定义了一
此文档下载收益归作者所有