对于随后的长篇文章感到抱歉。
我知道混合Microsoft提供的静态链接和动态链接的C和C ++运行时并不是一个好主意。我们在工作中的应用已经不幸地混合了它们,我们一直在努力解决这个问题。由于各种原因(其中我们不熟悉MSI,我们使用的NSIS可能不支持MSM,缺乏时间和资源)我们决定静态链接CRT而不是动态链接。我知道为什么这不是一个好主意,但这是我们现在的选择。
我们的代码主要是标准C ++,并辅以很多其他开源库。
应用程序的结构是:各种模块导致静态库本身被链接在一起以创建各种东西,其中一个可执行文件给我们带来了问题。
在发布中,我们使用/ MT构建所有我们的代码。对于一些开源库,我们使用预编译的二进制文件,其中一些是使用/ MD预编译的dll,这使得我们混合了运行时。所以我们用/ MT重新编译了这些,并使它们成为静态库而不是dll。没有为每个库进行此转换,因此我们仍然会链接一些使用/ MD的dll。
现在的结果是,在depends.exe中我们所有的东西除了一个可执行文件不直接依赖于msvcr80.dll或msvcp80.dll。通过不直接依赖我的意思是msvcr80.dll不是depends.exe显示的树根的子节点。有时我们确实发现msvcr80.dll被其中一个库dll拉入,但是在树中更深层次。
如何找到msvcr80.dll为什么是第一级的那个讨厌的可执行文件?是什么让这个可执行文件直接链接到msvcr80.dll?
一个原因可能是我们静态链接到链接使用/ MD的库A,因此它与CRT动态链接。所以库A中的代码最终在我们的可执行文件中,所以我们的可执行文件链接到msvcr80.dll。但是,我如何找出哪个库做到了?
到目前为止我尝试了什么:
Searching C:\Program Files\Microsoft Visual Studio 8\VC\lib\msvcrt.lib: Found "public: virtual void * __thiscall type_info::`vector deleting destructor'(unsigned int)" (??_Etype_info@@UAEPAXI@Z) Referenced in libcmt.lib(typinfo.obj) Loaded msvcrt.lib(ti_inst.obj) msvcrt.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in libcmt.lib(typinfo.obj) msvcrt.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in libcmt.lib(typinfo.obj) Found "void __stdcall `eh vector destructor iterator'(void *,unsigned int,int,void (__thiscall*)(void *))" (??_M@YGXPAXIHP6EX0@Z@Z) Referenced in msvcrt.lib(ti_inst.obj) Loaded msvcrt.lib(ehvecdtr.obj)
据我所知,libcmt.lib中的typinfo.obj引用一个符号,在msvcrt.lib中搜索它,然后在ti_inst.obj中找到它后会抛出一个错误,它定义了两次。但这没有意义。如果libcmt.lib已经有了符号,为什么它最终会在msvcrt.lib中搜索它并因此在我的可执行文件中引入msvcr80.dll?更一般地说,为什么静态库会在动态导入库中搜索符号?为什么链接器甚至会查看msvcrt.lib,如果我在Ignore特定库中有它?
感谢您的耐心: - )。
答案 0 :(得分:3)
我有解决问题的方法。这可能是古代遗留下来的一个愚蠢的错误。
我们在附加依赖项框中明确提到了msvcrt.lib :-(所以当然它使dll成为一个依赖项。而且因为所有的开源库都有很多文本,所以我们没有注意它。说实话,我们甚至没有想过仔细查看那个方框,因为我们没想到在我们的项目中会出现如此严重的错误。
答案 1 :(得分:1)
使用depends.exe打开您的可执行文件并运行内置于depends的探查器。我相信这会记录为什么你的所有dll都被加载,以及加载它们的位置。请参阅“Log LoadLibrary函数调用”选项。