科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件解决出现的LNK2005“符号已定义”错误 (6)

解决出现的LNK2005“符号已定义”错误 (6)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

解决出现的LNK2005“符号已定义”错误

作者:soloist 来源:Blog 2007年10月27日

关键字: LNK2005 Linux

  • 评论
  • 分享微博
  • 分享邮件

一开始E、U、D为空,链接器扫描main.obj,把它加入E,把foo加入U,把main加入D,把libc.lib加入到当前输入文件列表的末尾。接着扫描my.lib,foo从U转移到D,_malloc_dbg加入到U,libcd.lib加到当前输入文件列表的尾部。然后扫描libc.lib,这时会发现libc.lib里任何一个目标模块都没有定义_malloc_dbg(它只在调试版的标准库中存在),所以不会有任何一个模块因为_malloc_dbg而加入E,但是每个程序都要用到的初始化模块(如crt0.obj等)及它们所引用的模块(比如malloc.obj、free.obj等)还是会自动加入到E中,同时U和D被更新以反应这个变化。当链接器处理完libc.lib时,U只剩_malloc_dbg这一个符号。最后处理libcd.lib,发现dbgheap.obj定义了_malloc_dbg,于是dbgheap.obj加入到E,它里头的未解析符号加入U,它定义的所有其它符号也加入D,这时灾难便来了。之前malloc等符号已经在D中(随着libc.lib里的malloc.obj加入E而加入的),而dbgheap.obj又定义了包括malloc在内的许多同名符号,这引发了重定义冲突,链接器只好中断工作并报告错误。

    现在我们该知道,链接器完全没有责任,责任在我们自己的身上。是我们粗心地把缺省标准库版本不一致的目标文件(main.obj)与程序库(my.lib)链接起来,导致了大灾难。解决办法很简单,要么用/MLd选项来重编译main.c;要么用/ML选项重编译mylib.c。

    在上述例子中,我们拥有库my.lib的源代码(mylib.c),所以可以用不同的选项重新编译这些源代码并再次打包。可如果使用的是第三方的库,它并没有提供源代码,那么我们就只有改变自己程序的编译选项来适应这些库了。但是如何知道库中目标模块指定的默认库呢?其实VC提供的一个小工具便可以完成任务,这就是dumpbin.exe。运行下面这个命令

dumpbin /DIRECTIVES my.lib

  然后在输出中找那些"Linker Directives"引导的信息,你一定会发现每一处这样的信息都会包含若干个类似"-defaultlib:XXXX"这样的字符串,其中XXXX便代表目标模块指定的缺省库名。

  知道了第三方库指定的默认标准库,再用合适的选项编译我们的应用程序,就可以避免LNK2005和LNK1169链接错误。喜欢IDE的朋友,你一样可以到 "Project属性" -> "C/C++" -> "代码生成(code generation)" -> "运行时库(run-time library)" 项下设置应用程序的默认标准库版本,这与命令行选项的效果是一样的。

查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章