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

Posted

技术标签:

【中文标题】将静态库转换为 DLL 在 main 之前导致访问冲突【英文标题】:Converting static library to DLL causes access violation before main 【发布时间】:2018-01-30 21:48:24 【问题描述】:

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

事件库

winmm.dll(用于计时功能)

应用程序库

eventLibrary.lib(静态)

测试用例

eventLibrary.lib(静态) appLibrary.lib(静态) gtestd.lib(静态,Google 测试框架)

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

我将eventLibrary.lib 转换为一个DLL,它与我们的exe 进行构建和链接,但在它们到达main 之前就崩溃了。我正在使用 def 文件而不是修改库源。如果我从testCase.exe 中删除eventLibrary.dll 依赖项并从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 测试框架中的全局变量初始化期间,该框架仍然是一个静态库。调用栈如下:

testCase.exe!testing::Message::operator

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

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

将静态 windows 库转换为 dll

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

将dll转换为lib以进行静态链接?

将静态库和动态库链接到相同的可执行文件会导致哪些问题?

在 Visual Studio 中构建 DLL 时使用静态库

怎么分析静态链接库里都有哪些函数