【发布时间】:2019-09-19 14:45:29
【问题描述】:
背景:
有时,我的 MFC dApp 正在开发的程序中出现泄漏。 MFC 很好地将检测到的泄漏块转储到 Visual Studio 的输出窗格中,显示它们的 {block number} 和十六进制地址。一些泄漏没有源文件路径和行号,除了 fx strcore.cpp 等。这些泄漏的来源很难找到,需要更好的解决方案。
研究 WinDbg Preview 及其 Time Travel Debugging (TTD),我可以看到这是快速找到 MFC 硬漏洞的正确工具。
泄漏查找测试:
我创建了一个小型 MFC 程序并在其中放了一个漏洞:
void LeakInThread()
{
int* intLeak = new int[ 500 ];
}
wchar* leak = new wchar[ 100 ];
std::thread t1( LeakInThread ); // added leak in thread
t1.join();
节目制作:{274698} normal block at 0x000001AFA34D9790, 200 bytes long.
我使用 WinDbg 创建了一个 Trace 文件,Time Traveled 到最后以确保创建了泄漏,并使用 WinDbg commnd !heap -i x000001AFA34D9790 来定位发生错误的 TTD 块。这是输出:
0:000> !heap -i 0x00000180F42E3790
Detailed information for block entry 00000180f42e3790
Assumed heap : 0x0000000000000000 (Use !heap -i NewHeapHandle to change)
Header content : 0xCDCDCDCD 0xCDCDCDCD
Block flags : 0x1 LFH (busy )
Total block size : 0x0 units (0x0 bytes)
Requested size : 0xffffec00 bytes (unused 0x1400 bytes)
Subsegment : 0x25dac2f1e46abc2eUser blocks not available
问题:是否有 WinDbg 命令在 WinDbg 源代码窗格中显示文件和行号?
编辑1:
用这个查询命令做实验:
dx -g @$MemRes = @$cursession.TTD.Resources.HeapMemory
得到:
======================================================================================================================================
= = ResourceId = ResourceIdNew = Size = Function = ThreadId = UniqueThreadId = Position =
======================================================================================================================================
= [0x0] - 0x180f4282870 - 0x0 - 0x4c - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - C819:58 =
= [0x1] - 0x180f42b79d0 - 0x0 - 0x48 - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - 5545:62 =
= [0x2] - 0x180f4282870 - 0x0 - 0x0 - ntdll!RtlFreeHeap - 0x59e4 - 0x2 - C827:13F =
= [0x3] - 0x180f42b32a0 - 0x0 - 0x6a - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - 2E1C:58 =
= [0x4] - 0x180f744d330 - 0x0 - 0x24 - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - 9609:4C =
= [0x5] - 0x180f74572e0 - 0x0 - 0x48 - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - 960C:20D =
= [0x6] - 0x180f42b32a0 - 0x0 - 0x0 - ntdll!RtlFreeHeap - 0x59e4 - 0x2 - 2E23:147 =
= [0x7] - 0x180f42c1990 - 0x0 - 0x6a - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - FB23:58 =
= [0x8] - 0x180f42d9fd0 - 0x0 - 0x0 - ntdll!RtlFreeHeap - 0x59e4 - 0x2 - 12D1B:13F =
= [0x9] - 0x180f42c1990 - 0x0 - 0x0 - ntdll!RtlFreeHeap - 0x59e4 - 0x2 - FB2A:147 =
= [0xa] - 0x180f7453160 - 0x0 - 0x30 - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - 9625:4C =
= [0xb] - 0x180f42c0810 - 0x0 - 0x6a - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - FB2E:58 =
= [0xc] - 0x180f42b9160 - 0x0 - 0x0 - ntdll!RtlFreeHeap - 0x59e4 - 0x2 - 2E25:4B =
= [0xd] - 0x180f42e9bd0 - 0x0 - 0x0 - ntdll!RtlFreeHeap - 0x59e4 - 0x2 - 15481:13F =
= [0xe] - 0x180f42d9fd0 - 0x0 - 0x4c - ntdll!RtlAllocateHeap - 0x59e4 - 0x2 - 12D0D:58 =
= [...]
由于ResourceID 看起来类似于 MFC 输出地址,我使用此选择查询缩小了输出范围:
dx -g @$MemRes.Where(x => x.ResourceId == 0x00000180F42E3790)
但输出网格没有结果。
编辑2:
“如果泄漏发生在 MainFrame 线程中,源文件和行号也会显示。当泄漏发生在另一个衍生线程中时不会。”不是真的。但是确实会发生不指向其源和行号的泄漏。 MFC 调试器程序仍有可能缺少某些源路径定义,允许它找到源代码。需要更多的研究。
编辑3:
经过进一步审查,我的 MFC 程序产生的泄漏,即使在启动后没有按下任何键,每次运行时都有不同的数据地址。 (泄漏是在许多签到之前引入的,直到现在才被注意到)。这意味着我不能使用 WinDbg TTD 的 dx ... 命令迭代跟踪的帧,将数据地址与帧 LocalVariables Values 进行比较,因为每次程序运行时泄漏的数据地址都会不同,包括何时正在记录跟踪。但是,可以使用命令来确定程序结束时堆分配是否未完成。
【问题讨论】:
-
你的意思是你有汇编列表中的地址并想找到与该地址对应的来源?如果是 .open -a {your Address Here} 应该将您分配到源代码行或使用 lsa 。在哪里 。表示当前的 rip/eip
-
我尝试
.open -a 0x180f42e3790没有结果。查看堆栈帧中的 LocalVariables 我找到了leak 0x180f42e3790 : "췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍???" wchar_t *,所以我知道该地址是一个有效的程序集列表值并且在 Trace 中。 -
您的意思是您正在寻找与 new 运算符返回的内存地址相对应的源代码行,该操作符在幕后使用 heapalloc 或 virtualalloc?你不能得到它它是一个动态地址没有src行
-
如果您需要跟踪句柄、对象、调试堆、页面堆等,那么您可能需要查看 gflags.exe 选项并启用标志以获取这些堆栈跟踪
-
或分享您在说您制作了样本时被困在其中的垃圾箱
标签: debugging memory-leaks mfc windbg