最近帮同事查了一个C++链接过程的问题,这个问题比较隐蔽,也非常有代表性,记录下来方便后面查阅。

动态库和静态库

在软件开发中,通常将相似或具有关联性的代码归入一个模块中,这个模块会以动态库或静态库的形式独立出来。每个静态库或动态库会作为独立的编译单元生成目标文件,这些目标文件最终会被链接在一起。这些静态库和动态库之间大多具有依赖关系,在链接过程中如果所依赖的函数出现了缺失就会链接失败。

__imp_ 开头的函数缺失

同事的这个工程在以静态库方式链接时出现以 __imp_ 开头的函数缺失,通常情况下报这个问题是因为该函数没有定义。但是,在仔细观察函数的名称后发现该函数已经被定义出来了,这就很奇怪了。

使用dumpbin工具插件动态库的函数

查看与链接相关的函数名称

dumpbin /linkermember xxx.lib

在命令的输出结果中搜索能够找到该函数,但是函数名称前没有 __imp_ 前缀。查阅资料后发现 __imp_ 前缀是windows平台下动态库导出函数的前缀。

为什么在链接时寻找的是动态库版本的函数呢?这个与函数声明的头文件有关,由于头文件中使用了条件编译来区分动态库和静态库版本,而默认情况下使用动态库导出标识符 dllexport/dllimport ,将静态的宏定义加上后就能链接通过了。

tips:其他实用的dumpbin指令

查看静态库中的函数

dumpbin /symbols xxx.lib

查看动态库中的导出函数

dumpbin /exports xxx.dll

查看动态库的依赖库

dumpbin /dependents xxx.dll