使用 WinDbg,是否可以使用 WinDbg 命令突出显示 MFC 源代码中的源代码行?

Using WinDbg, is it possible to highlight the source line in MFC source code with WinDbg command?

背景:

偶尔,我在开发中的 MFC dApp 程序中遇到泄漏。 MFC 在 Visual Studio 的输出窗格中很好地转储检测到的泄漏块,显示它们的 {block number} 和十六进制地址。有些泄漏没有源文件路径和行号,除了 fx strcore.cpp 等。这些泄漏源很难找到,需要更好的解决方案。

通过时间旅行调试 (TTD) 研究 WinDbg 预览版,我可以看出这将如何成为快速找到硬 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 输出地址相似,我使用此 select 查询缩小了输出范围:

dx -g @$MemRes.Where(x => x.ResourceId == 0x00000180F42E3790)

但是输出网格没有结果。

编辑2:

"If the leak occurred in the MainFrame thread, the source file and line number are shown as well. No so when the leak occurred in another spawned thread." 不正确。但是确实会发生不指向其来源和行号的泄漏。 MFC 调试器程序仍有可能缺少某些源路径定义,从而使其无法找到源代码。需要更多的研究。

编辑3:

经过进一步审查,我的 MFC 程序产生的泄漏,即使在启动后没有按下任何键,每次 运行 时都有不同的数据地址。 (泄漏是在许多签到之前引入的,直到现在才被注意到)。这意味着我无法使用 WinDbg TTD 的 dx ... 命令遍历跟踪的帧,将数据地址与帧 LocalVariables Values 进行比较,因为泄漏的数据地址每次都会不同该程序是 运行,包括记录跟踪的时间。但是,但是,可以使用命令来确定程序结束时堆分配是否未完成。

如评论所述,我不确定您在寻找什么,这些是您可以尝试的几个选项

1) 您可以更改.asm 选项使反汇编列表显示行号和文件名

喜欢下面

.asm

1:001> .asm
Assembly options: <default>
1:001> u .
vect!main [f:\src\vect\vect.cpp @ 9]:
00007ff6`e1d7efb0 4881ec98000000  sub     rsp,98h
00007ff6`e1d7efb7 48c7442460feffffff mov   qword ptr [rsp+60h],0FFFFFFFFFFFFFFFEh
00007ff6`e1d7efc0 488d4c2448      lea     rcx,[rsp+48h]
00007ff6`e1d7efc5 e8576dffff      call    vect!ILT+19740(??0?
00007ff6`e1d7efca 90              nop
00007ff6`e1d7efcb c744242001000000 mov     dword ptr [rsp+20h],1
00007ff6`e1d7efd3 eb0a            jmp     vect!main+0x2f (00007ff6`e1d7efdf)
00007ff6`e1d7efd5 8b442420        mov     eax,dword ptr [rsp+20h]
1:001> .asm source_line
Assembly options: source_line
1:001> u .
vect!main [f:\src\vect\vect.cpp @ 9]:
    9 00007ff6`e1d7efb0 4881ec98000000  sub     rsp,98h
    9 00007ff6`e1d7efb7 48c7442460feffffff mov   qword ptr [rsp+60h],0FFFFFFFFFFFFFFFEh
   10 00007ff6`e1d7efc0 488d4c2448      lea     rcx,[rsp+48h]
   10 00007ff6`e1d7efc5 e8576dffff      call    vect!ILT+19740(??0?
   10 00007ff6`e1d7efca 90              nop
   12 00007ff6`e1d7efcb c744242001000000 mov     dword ptr [rsp+20h],1
   12 00007ff6`e1d7efd3 eb0a            jmp     vect!main+0x2f (00007ff6`e1d7efdf)
   12 00007ff6`e1d7efd5 8b442420        mov     eax,dword ptr [rsp+20h]

或者您可以使用 .open -a 地址打开一个新源 window

例如

.open -a .

打开对应于当前 Rip/Eip 的来源。 (点)表示当前指令指针

或者你可以使用 ls 命令

打印源代码行(使用 lsp 配置 pre 和 post 行数计数默认为 5 行 pre 5 行 post)

1:001> lsa .
     5: 
     6: using namespace std; 
     7: 
     8: int main() 
>    9: { 
    10:     vector<int> g1; 
    11: 
    12:     for (int i = 1; i <= 5; i++) 
    13:         g1.push_back(i); 
    14: 

为了识别 C++ 应用程序中泄漏的代码,我使用下面提供的命令 link。 https://www.codeproject.com/Articles/31382/Memory-Leak-Detection-Using-Windbg 希望这可以帮助。