将静态库转换为 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.lib
在appLibrary.dll
和testCase.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 之前导致访问冲突的主要内容,如果未能解决你的问题,请参考以下文章
将 std::vector 转换为数组然后 p/调用它会在编组期间导致 mscorlib.dll 中的访问冲突异常