我怎样才能找到什么让我的应用程序混合静态和动态链接的CRT

问题描述:

对不起,接下来的长篇文章。我怎样才能找到什么让我的应用程序混合静态和动态链接的CRT

我知道混合由Microsoft提供的静态链接和动态链接的C和C++运行时并不是一个好主意。我们在工作中的应用程序已经将它们混合在一起,我们一直在努力解决这个问题。出于各种原因(其中不熟悉MSI,我们使用NSIS,可能不支持MSM,缺乏时间和资源),我们决定静态链接CRT而不是动态链接。我知道这不是一个好主意的原因,但现在是我们的选择。


我们的代码大多是标准的C++,还有很多其他的开源库。

该应用程序的结构是:各种模块导致静态库,它们本身链接在一起创建各种东西,其中一个可执行文件给我们提供了问题。

在发布我们建立所有我们的代码与/吨。对于一些开源库,我们使用了预编译的二进制文件,其中一些是使用/ MD预编译的dll,这使我们混合了运行时。所以我们用/ MT重新编译了这些文件,并将它们导致静态库不是dll。这个转换不是为每个库完成的,所以我们仍然使用一些使用/ MD的dll。


结果现在是,所有的Depends.exe我们的东西除了一个可执行直接取决于MSVCR80.DLL或msvcp80.dll。由不直接依赖我的意思是msvcr80.dll不是由depend.exe显示的树的根的孩子。有时候我们会发现msvcr80.dll被其中一个库DLL引入,但是这个树更深一些。

如何找出为什么msvcr80.dll在第一级为那个麻烦的可执行文件?什么使该可执行文件直接链接到msvcr80.dll?

其中一个原因可能是我们静态链接到链接使用/ MD的库A,因此它与CRT动态链接。因此,库A中的代码以可执行文件结尾,以便我们的可执行文件与msvcr80.dll链接。但是,我怎么知道哪一个库能够做到这一点?


我试过到目前为止:

  • 负载静态链接的.lib文件中带的Depends.exe - >不起作用,因为预计的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)" ([email protected]@[email protected]) 
     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 &)" ([email protected]@[email protected]@@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 &)" ([email protected]@[email protected]@@Z) already defined in libcmt.lib(typinfo.obj) 
     Found "void __stdcall `eh vector destructor iterator'(void *,unsigned int,int,void (__thiscall*)(void *))" ([email protected]@[email protected]) 
     Referenced in msvcrt.lib(ti_inst.obj) 
     Loaded msvcrt.lib(ehvecdtr.obj) 

据我了解,在typinfo.obj引用LIBCMT.LIB一个符号,搜索它在MSVCRT.LIB并在ti_inst.obj发现后,它抛出一个错误它被定义了两次。但这没有意义。如果libcmt.lib已经有这个符号,为什么它最终会在msvcrt.lib中搜索它,并因此在我的可执行文件中引入msvcr80.dll?更一般地说,为什么静态库会在动态导入库中搜索符号?为什么链接器甚至可以查看msvcrt.lib,如果我在忽略特定库中有它?

感谢您的耐心:-)。

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

msvcrt.lib被我们在附加依赖框中明确提到:-(所以当然它使得dll成为一个依赖关系,而且由于所有的开源库都包含很多文本,所以我们并没有这么做,老实说,我们甚至没有仔细看过那个盒子,因为我们没有想到在我们的项目中可能会出现这样的严重错误

使用depends.exe打开您的可执行文件并运行内置于依赖的分析器。我相信这会记录你为什么加载了所有的dll,以及它们从哪里加载。请参阅“日志LoadLibrary函数调用”选项。

+0

感谢您的建议。我的应用程序会调用msvcrt80.dll上的LoadLibrary,所以如果该dll会延迟加载,但我直接链接到它,所以我只看到:加载“MSVCR80.DLL”在地址0x78130000由线程1成功挂钩模块 问题原来是由一个愚蠢的错误造成的,请参阅我的答案。 –