

调试实战 | 解决另外一个链接错误
source link: https://bianchengnan.gitee.io//articles/troubleshoot-LNK2001-unresovled-external-symbol-error/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近,在加班的过程中遇到一个链接错误 —— fatal error LNK1120: 1 unresolved externals
。这种错误是老朋友了,对我这种常年写 bug
的老手来说,完全不是事儿,轻松+愉快。
根据以下的排查思路基本上能解决大多数链接错误:
既然报了链接错误,说明编译已经通过了,问题基本出现在库文件上。
有可能是找不到库文件(缺少库,或者库文件搜索路径不对),可以先确认工程配置是否正确或者使用 /verbose:lib
查看链接过程。
也可能是库文件不对(没包含对应的导出符号),可以通过 dumpbin /exports error.lib > error.txt
查看 lib
库中的导出符号。按照以上步骤排查基本上可以解决绝大多数链接错误。
好的,让我们一起来实战一下吧。
说明: 实际项目需要保密,本文的截图是我在本地用测试工程做的。
确保 lib 存在并且路径正确
通过查看工程设置可以得知,依赖的库文件是 TestLNK1120Dll.lib
,附加库目录中也添加了这个 lib
所在的路径。肉眼看上去没问题。为了保险(之前遇到过更诡异的错误,配置看上去都对,但是实际的值不对),还是通过 /verbose:lib
选项看一下链接过程。
在对应工程上,右键 -> 属性 -> Configuration Property -> Linker -> Command Line
,在 Additional Options
下面输入 /verbose:lib
即可。
设置好后,重新编译。可以看到链接时整个库查找过程,如下图。
至此,可以确定库文件路径配置没错,那大概率是库文件中的符号与程序中的符号不匹配导致的。
说明: 如果找不到
.lib
文件,报错应该类似下面这样:
fatal error LNK1104: cannot open file 'TestLNK1120Dll.lib'
查看 lib 文件中的导出符号
使用 dumpbin
可以查看 lib
库中的所有导出符号,命令如下:
dumpbin /exports d:\test\TestLNK1120.lib > d:\TestLNK1120.txt
注意: 以上命令需要在
dumpbin.exe
所在目录下执行,或者启动Developer Command Prompt for VS xxx
。
然后根据 vs
编译错误提示中的符号在 TestLNK1120.txt
中搜索,应该是没有匹配项目。
搜索报错的符号
确实可以在 TestLNK1120.txt
中根据函数名 GetStaticData
搜到相关记录,但是根据完整的符号名称搜不到。
TestLNK1120.txt
文件中与 GetStaticData
相关的内容是:
?GetStaticData@@YAAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ (class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __cdecl GetStaticData(void))
而 vs
报错提示是:
TestLNK1120.obj : error LNK2001: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl GetStaticData(void)" (?GetStaticData@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
让我们对比一下这两个结果哪里不一样。
别看上面的输出很多很乱,其实我们最需要关心的是经过名字改编的符号名。
vs
中经过名字改编后的符号名是
?GetStaticData@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ
lib
库中经过名字改编后的符号名是
?GetStaticData@@YAAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ
如果仔细看,确实能发现这两个输出结果是不一样的,但是经过编译器处理的符号名非常不适合人类阅读。如果能看到函数原型就太好了。
其实,上面的输出结果既包含了函数原型,又包含了经过名字改编后的符号名。
vs
中的函数名:
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl GetStaticData(void)
lib
库中的函数名:
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __cdecl GetStaticData(void)
可以发现,lib
库中提供的函数的返回值是引用类型的,而 vs
中函数的返回值是不带引用的。
至此就破案了!
undname 工具
如果只有经过名字改编后的符号名,可以通过微软提供的 undname.exe
工具来翻译成人类友好的名称。
可以到 gitee 上下载示例工程。
dumpbin.exe
可以查看 lib
库中的符号信息
undname.exe
可以非常方便的查看未经过编译器处理的函数名
Recommend
-
9
前四节介绍如何定制自己的 linux 内核,以及如何利用 busybox 制作文件系统,如何使用 qemu 模拟器运行编译好的 linux 内核。上一节介绍了在没有界面和鼠标的 linux 环境下,如何使用 gdb 工具单步调试程序。linux 内核也可以看作是一个程序,所以本节将尝试使...
-
16
一个节点挂导致另外一个节点也跟着挂的案例一则 版权声明:本文为Buddy Yuan原创文章,转载请注明出处。原文地址:
-
8
解决Hugo的错误链接localhost 2017-06-23 18:12:07 +08 字数:608 标签: Hugo 问题
-
9
阅读时间大约10分钟以上(6832字) ...
-
8
解决 C++ 链接到一个绝对路径的动态链接库 作者: 张志强 ...
-
10
将一个带UI的项目打成jar包,在另外的项目中引用并访问?
-
12
另外一个视野下的「崭新」开始原创 | 须佐能乎 监制 | 李安嶙▼在商业世界里,华为任正非有一个事迹,十分令人鼓舞,是一个与 200 万有关的事迹。****大致,在任正非 44 岁的时候,因为经营,他被骗 200 万公款,当时的 200 万相当于现在的 2000...
-
4
OYO,孙正义的另外一个烂摊子 作者:AG 来源:格隆汇IPO研究院 在印度这个神话色...
-
9
如何将git的master分支整个替换为另外一个分支 – 某人的栖息地 Skip to the content 我有一个git仓库,其中master分支的代码已经落后几个月了,而另外一个blah分...
-
16
V2EX › Google 如何转移 Google Drive 文件夹到另外一个 Google 账户
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK