微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

MFC:为什么会发生这种堆损坏? (array_s.cpp / afxcoll.inl) 崩溃代码问题出在哪里项目设置问题更新内存管理

如何解决MFC:为什么会发生这种堆损坏? (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() 是静态的

  • 请注意,这实际上不是我的代码,而只是我可以重现错误的最低限度。它也可以用 CArray 重现。

  • 我证实,堆损坏确实不会发生之前代码行通过 gflags /p /enable MyExe.exe /full

堆栈跟踪:

StackTrace


问题出在哪里

DLL 依赖 MFC 源
1 CStringArray 创建 MyExe.exe > MFC ...\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\array_s.cpp
2 内部数组分配 MyExe.exe > MyDll.dll > MFC ...\Microsoft Visual Studio 10.0\VC\atlmfc\include\afxcoll.inl
3 删除 MyExe.exe > MFC ...\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\array_s.cpp

内部数组的删除方式与创建方式不同,这一事实可能是错误所在。 (如有不对请指正)


项目设置

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

MFC 的使用 在共享 DLL 中使用 MFC
ATL 的使用 未使用 ATL
字符集 使用 Unicode 字符集

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


问题

MyDll.dll 不是唯一加载的 dll,项目依赖项(对第三方 dll 等)有太多发生,所以我无法将所有这部分作为我的问题。

所以我的问题归结为:

  • 我的假设正确,即 array_s.cpp 和 afxcoll.inl 彼此不兼容?
  • 是什么让一段代码调用 array_s.cpp,另一段代码调用 afxcoll.inl?
  • 还有什么问题?

我试过关掉再打开;)

先谢谢你!


更新

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

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

解决方法

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

但是,如果您的 DLL 正在定义自己的 MFC 派生类(您的 ClassInDll 似乎是这样),则它确实应该构建为 MFC Extension DLL

构建扩展 DLL(甚至使用“常规”MFC DLL)的整个过程对我来说过于宽泛,无法在此为您提供任何可用的源代码。但是,从上面的第二个链接,以下部分可能与您看到的问题有关(粗斜体是我的):

内存管理

MFCx0.dll 和加载到客户端的所有 MFC 扩展 DLL 应用程序的地址空间使用相同的内存分配器,资源 加载和其他 MFC 全局状态就好像它们处于相同 应用。这很重要,因为非 MFC DLL 库和 常规的 MFC DLL 做的恰恰相反 并且让每个 DLL 分配出自己的内存池

如果 MFC 扩展 DLL 分配内存,则该内存可以自由地 与任何其他应用程序分配的对象混合。另外,如果一个 动态链接到 MFC 的应用程序失败,保护 操作系统维护任何其他 MFC 应用程序的完整性 共享 DLL。

类似的其他全局 MFC 状态,比如当前的可执行文件到 从加载资源,也在客户端应用程序之间共享 和所有 MFC 扩展 DLL 以及 MFCx0.dll 本身。

,

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

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

“模块”窗口确实有帮助,如果您只知道应该查看那里。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?