将静态库转换为DLL会导致在main之前发生访问冲突

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将静态库转换为DLL会导致在main之前发生访问冲突相关的知识,希望对你有一定的参考价值。

我们在VS2015中有一个大型解决方案,它有两个库和许多用于测试我们应用程序的win32项目。我们的项目及其依赖关系如下:

  • 活动图书馆 winmm.dll(用于计时功能)
  • 应用程序库 eventLibrary.lib(静态)
  • 测试用例 eventLibrary.lib(静态) appLibrary.lib(静态) gtestd.lib(静态,谷歌测试框架)

这些库最初是静态的,但我们将它们转换为DLL以便更快地进行链接。我用__declspec(dllexport)装饰器修改了我们的应用程序代码,并成功编译并链接我们的应用程序作为DLL。所有不使用eventLibrary.lib并且成功运行的测试用例,其余的崩溃因为eventLibrary.libappLibrary.dlltestCase.exe中静态连接。

我将eventLibrary.lib转换为DLL,它与我们的exes构建并链接,但在它们到达main之前崩溃。我正在使用def文件而不是修改库源。如果我从eventLibrary.dll中删除testCase.exe依赖项并从appLibrary.dll导出其符号,则会发生完全相同的崩溃。

崩溃是在ostream超载的<<运营商内部。传入的stringstream(下面的参数_Ostr)与使用静态库构建时相同。我得到一个0xC0000005: Access violation executing location 0x0D20E4E9,这似乎是由调用width方法引起的:

template<class _Traits> inline
    basic_ostream<char, _Traits>& operator<<(
        basic_ostream<char, _Traits>& _Ostr,
        const char *_Val)
    {   // insert NTBS into char stream
    typedef char _Elem;
    typedef basic_ostream<_Elem, _Traits> _Myos;
    ios_base::iostate _State = ios_base::goodbit;
    streamsize _Count = (streamsize)_Traits::length(_Val);  // may overflow
    streamsize _Pad = _Ostr.width() <= 0 || _Ostr.width() <= _Count
        ? 0 : _Ostr.width() - _Count; // <- Dies here

这发生在Google Test框架中的全局变量初始化过程中,该框架仍然是一个静态库。调用堆栈如下:

testCase.exe!testing :: Message :: operator <<(const char [7]&val)第131行testCase.exe!testing :: internal :: FlagToEnvVar(const char * flag)第1136行testCase.exe!testing :: internal :: BoolFromGTestEnv(const char * flag,bool default_value)第1195行testCase.exe!testing ::`'FLAGS_gtest_also_run_disabled_tests'的动态初始化程序'()第202行

动态链接我们的事件库以某种方式破坏testCase.exe中的内存?这有没有与拥有自己的堆的DLL有关?我确保在构建和链接时使用相同的运行时(/MDd)和相同的标志编译我们的DLL和exes。

答案

我通过将两个库源放在同一个DLL中解决了这个问题。我们的事件库实际上已经定义了用于导出到DLL的宏,并且我们通过组合这两者来消除任何依赖性问题。

以上是关于将静态库转换为DLL会导致在main之前发生访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

将静态 windows 库转换为 dll

在执行任何程序代码之前,通过静态 .lib 链接到 dll 的程序会发生啥?

VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结

VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结

VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结

将 std::vector 转换为数组然后 p/调用它会在编组期间导致 mscorlib.dll 中的访问冲突异常