如何找出使我的应用程序混合静态和动态链接的CRT的原因

时间:2009-10-14 21:51:43

标签: visual-c++ dynamic-linking msvcrt static-linking

对于随后的长篇文章感到抱歉。

我知道混合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。但是,我如何找出哪个库做到了?


到目前为止我尝试了什么:

  • 在depends.exe中加载静态链接的.lib文件 - >因为depends.exe期望可执行文件或DLL不是静态库
  • ,所以不起作用
  • 在静态链接的.lib文件上使用dumpbin.exe / DIRECTIVES - >他们都没有显示msvcrt80.dll(在Debug中,我们尝试使用/ MDd进行所有操作,他们确实显示了msvcrt80d.dll,这让我觉得方法很好,它证明了所有静态链接的开源库都已编译正确使用/ MT)
  • 使用/ VERBOSE:LIB链接器标志 - >它表明确实它正在拉入msvcrt.lib这是msvcr80.dll的导入库所以我们遇到了麻烦,但它没有说明为什么会这样做
  • 在Visual Studio中使用/ VERBOSE链接器标志+:附加依赖项libcmt.lib +忽略所有默认库YES +忽略特定库:msvcrt.lib,迫切想要使msvcrt.lib消失或看谁拉它。结果让我难过:
    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特定库中有它?

感谢您的耐心: - )。

2 个答案:

答案 0 :(得分:3)

我有解决问题的方法。这可能是古代遗留下来的一个愚蠢的错误。

我们在附加依赖项框中明确提到了msvcrt.lib :-(所以当然它使dll成为一个依赖项。而且因为所有的开源库都有很多文本,所以我们没有注意它。说实话,我们甚至没有想过仔细查看那个方框,因为我们没想到在我们的项目中会出现如此严重的错误。

答案 1 :(得分:1)

使用depends.exe打开您的可执行文件并运行内置于depends的探查器。我相信这会记录为什么你的所有dll都被加载,以及加载它们的位置。请参阅“Log LoadLibrary函数调用”选项。