MFC:为什么会发生这种堆损坏? (array_s.cpp / afxcoll.inl)

MFC: Why does this heap corruption happen? (array_s.cpp / afxcoll.inl)

崩溃代码

当调用第三行('delete' 命令)时,以下代码使我的程序因堆损坏而崩溃(程序退出):

1: CStringArray* pStringArray = new CStringArray();
2: ClassInDll::addToStringArray(_T("asdf"), *pStringArray);
3: delete pStringArray;

1: ClassInDll::addToStringArray(CString s, CStringArray& sa){
2:  sa.Add(s);
3: }

addToStringArray() 是静态的

堆栈跟踪:


好像是什么问题

Dll dependency MFC source
1 CStringArray creation MyExe.exe > MFC ...\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\array_s.cpp
2 Internal array allocation MyExe.exe > MyDll.dll > MFC ...\Microsoft Visual Studio 10.0\VC\atlmfc\include\afxcoll.inl
3 Deletion MyExe.exe > MFC ...\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\array_s.cpp

内部数组没有按照创建时的方式删除,这可能是错误所在。 (如有错误请指正)


项目设置

我确保在 MyExe.exe 和 MyDll.dll 中使用相同的 MFC 设置,即:

Use of MFC Use MFC in a Shared DLL
Use of ATL Not using ATL
Character Set Use Unicode Character Set

我在调试模式下测试,所以没有优化。


问题

MyDll.dll 不是唯一加载的 dll,而且项目依赖项(对第三方 dll 等)有太多影响,所以我不能把这部分问题全部提出来。

所以我的问题归结为:

我试过将其关闭再打开 ;)

提前致谢!


更新

PaulMcKenzie 指出,如果我针对不同的 CRT 进行构建,情况就是如此。一个是“多线程调试 DLL”,另一个是“多线程 DLL”。在使两者相等之后,问题仍然存在。 This page 声明如果使用 VS 2015 及更高版本 Windows 10 并具有项目设置以便使用相同的运行时库,则在运行时使用相同的 CRT 库(因此应该使用相同的堆,对吧?)。

我已经确定,“项目属性 -> C/C++ -> 代码生成”中的每个条目在 exe 和 dll 中都完全相同。

在模块(EXE 和 DLL,或不同的 DLL)之间传递 MFC 对象(甚至 通过 指针)是一件 非常 棘手的事情。如果您只是在 DLL 中 使用 类,那么您应该(至少)使用 AFX_MANAGE_STATE 宏(参见 here ) 在 DLL 中。

但是,如果你的 DLL 是定义它自己的 MFC 派生的类(你的ClassInDll 似乎是这样),它真的应该构建作为 MFC Extension DLL.

构建扩展 DLL(甚至使用 'regular' MFC DLL)的整个过程过于宽泛,我无法在这里为您提供任何可用的源代码。但是,从上面的第二个 link 开始,以下部分可能与您看到的问题相关(粗体斜体是我的):

Memory Management

MFCx0.dll and all MFC extension DLLs loaded into a client application's address space use the same memory allocator, resource loading, and other MFC global states as if they were in the same application. This is significant because the non-MFC DLL libraries and the regular MFC DLLs do the exact opposite and have each DLL allocating out of its own memory pool.

If an MFC extension DLL allocates memory, that memory can freely intermix with any other application-allocated object. Also, if an application that dynamically links to MFC fails, the protection of the operating system maintains the integrity of any other MFC application sharing the DLL.

Similarly other global MFC states, like the current executable file to load resources from, are also shared between the client application and all MFC extension DLLs as well as MFCx0.dll itself.

事实证明,发布 调试 dll 都被加载(因为另一个 dll):

  • msvcr100.dll
  • msvcr100d.dll
  • msvcp100.dll
  • msvcp100d.dll

“模块”window 肯定有帮助,如果你只知道你应该看看那里。

感谢 PaulMcKenzie 和 IInspectable 引领我走向正确的方向。