visual-c++ - 如何从托管 C# 代码跟踪 CRT 调试内存泄漏输出的来源?
问题描述
我正在运行一个用 C# (WPF) 编写的软件,该软件使用了大量本机遗留代码。当我关闭软件时,调试器会继续运行,并且我的调试输出屏幕会打印以下内容:
Detected memory leaks!
Dumping objects ->
{41198} normal block at 0x00000211F11C58F0, 16 bytes long.
Data: < > D8 CE DF B0 8D 00 00 00 00 00 00 00 00 00 00 00
{41194} normal block at 0x00000211C66AD710, 96 bytes long.
Data: <D:\mydir\somedir> 44 3A 5C 72 65 70 6F 5C 69 71 73 2D 74 72 75 6E
{41193} normal block at 0x00000211F11C5210, 16 bytes long.
Data: < > 80 83 A1 E1 11 02 00 00 00 00 00 00 00 00 00 00
{41192} normal block at 0x00000211E1A18360, 88 bytes long.
Data: < > 90 80 9D E0 11 02 00 00 90 80 9D E0 11 02 00 00
(Repeated)
(我将那里显示的路径更改为“mydir\somedir”)
这些消息可能会持续超过一分钟,直到我从“停止调试”按钮关闭它。
该软件使用许多用 C 和 C++ 编写的库。有几个 C++/CLI 项目作为包装器执行并由 C# 代码使用。
我确实可以访问正在使用的本机源代码,因此我按照 MSDN 中的说明_CRTDBG_MAP_ALLOC
搜索并重新定义了new
运算符的所有定义,但输出保持不变并且没有显示任何行/文件信息。我什至不确定它是否来自我们的代码。
如何追踪此内存泄漏的来源?有没有办法至少确定是什么文件/项目导致了这种情况?假设这是来自我们的代码,有没有办法使用 C++/CLI 代码来调试它?
解决方案
问题实际上出在 C++/CLI 包装器中。
所有负责释放内存的代码都写在类的析构函数中,假设它们将被垃圾收集器自动调用。
然而,事实证明 GC 并没有调用析构函数,而是调用了终结器。
解决方案是将所有代码从析构函数移动到终结器,然后当我关闭程序时调试输出中不会显示任何转储行,并且当 GC 运行并且该类被认为已死时释放内存。
推荐阅读
- popupwindow - 如何使用 userscript 和 tempmonkey 检索弹出窗口的 html 源代码
- reactjs - 创建并发布一个没有自己的 node_modules 的 node_modules 包
- javascript - 表格的颜色单元格
- javascript - Wordpress 无法保存特色图片
- node.js - Oracle DB 与 Node.js 的连接出现“错误:未设置模式用户名!尝试设置环境变量 NODE_ORACLEDB_USER。”
- java - PDF 立即打开和关闭
- c# - 当我尝试从 ViewModel 以编程方式设置工具栏徽章计数时,它不起作用
- c# - 如何使用 StackExchange.Redis 通过 redis URL 连接到 redis 缓存?
- django - 如何使用默认 timezone.now 在 django datetimefield 中查询特定日期?
- java - Spring如何通过XML向队列注入值