0

我正在调试转储文件,同时我可以访问符号文件。

我正在使用一个脚本,它结合了以下windbg命令的结果:

x /2 *!*  // which types are present in the symbol files?
!heap -h 0 // which memory address ranges are used in the dump?

(至少,我是这么理解的。如果我错了,请毫不犹豫地纠正我)

脚本的结果(称为heap_stat.py,可在此 Windbg 扩展列表下找到)是内存地址列表,后跟它们的类型。如果存在内存泄漏,我可以通过统计这些数据得出。

最重要的是,使用提到的内存地址的 WinDbg 命令dt CStringArray m_nSize(当然,在 a 的特定情况下CStringArray),我可以看到已使用对象的条目总数CStringArray,并查看是否存在CStringArray具有大量条目的对象。

然而,这个系统有一个缺点:
当我发现这样一个CStringArray有很多条目的对象时,我会卡在那里,因为CStringArray在我的应用程序中的所有对象中,我不知道我正在处理哪一个。

可能有帮助的一件事是内存地址所在的局部变量的名称,但有一个问题:我不知道此信息是否存在,如果是,我可以在符号文件或转储中找到它,以及(显然)我需要运行哪个命令才能获取此信息(我没有找到一个标志可以dt <flag> <memory address>返回局部变量名称,由 占用<memory address>)?

有谁能够帮我?

为澄清起见,这就是我的脚本的结果当前的样子:

0x0065a4d0  mfc110u!CStringArray  Size:[1]
0x0065a4e4  mfc110u!CStringArray  Size:[0]
0x0065a4f8  mfc110u!CStringArray  Size:[295926]
0x0065a520  mfc110u!CStringArray  Size:[0]

如您所见,我可以看到存储变量的内存地址,可以看到类型(从符号文件中检索),并且可以看到条目数量(从dt Windbg命令中检索),但我想有如下输出:

0x0065a4d0  mfc110u!CStringArray  Size:[1]      var1
0x0065a4e4  mfc110u!CStringArray  Size:[0]      var2
0x0065a4f8  mfc110u!CStringArray  Size:[295926] var3
0x0065a520  mfc110u!CStringArray  Size:[0]      var3

或者:

0x0065a4d0  mfc110u!CStringArray  Size:[1]      obj1.prop1
0x0065a4e4  mfc110u!CStringArray  Size:[0]      obj2.prop1
0x0065a4f8  mfc110u!CStringArray  Size:[295926] obj1.prop2
0x0065a520  mfc110u!CStringArray  Size:[0]      obj1.prop2

这样的输出将表明我需要验证源代码var3obj1.prop2源代码中发生了什么。

4

1 回答 1

1

我编写了以下 MFC 应用程序(部分来源):

CStringArray stringarray;
void* anotherarray = new CStringArray();

void CLocalVariableNameApp::AnotherMethod(void* a)
{
    CStringArray* temp = static_cast<CStringArray*>(a);
    temp->Add(L"Something else");
}

CLocalVariableNameApp::CLocalVariableNameApp()
{
    stringarray.Add(L"Something");
    AnotherMethod(anotherarray);
    CStringArray* holycow = static_cast<CStringArray*>(anotherarray);
    holycow->Add(L"Yet something else");
    DebugBreak();
}

如您所见,第二个 CStringArray 有多个名称:anotherarraya和。tempholycow

观察 1:内存地址和变量名不会有简单的 1:1 映射。

局部变量名称可从 PDB 文件中获得:

0:000> k
 # ChildEBP RetAddr  
00 0022fa40 00fa2a30 KERNELBASE!DebugBreak+0x2
01 0022fb3c 00f97958 LocalVariableName!CLocalVariableNameApp::CLocalVariableNameApp+0x90 [c:\...\localvariablename.cpp @ 38] 
02 0022fc10 014b628a LocalVariableName!`dynamic initializer for 'theApp''+0x28 [c:\...\localvariablename.cpp @ 43] 
03 0022fc18 014b5e8c LocalVariableName!_initterm+0x1a [f:\...\crt0dat.c @ 955] 
04 0022fc2c 014a9263 LocalVariableName!_cinit+0x6c [f:\...\crt0dat.c @ 308] 
05 0022fc78 014a947d LocalVariableName!__tmainCRTStartup+0xf3 [f:\...\crt0.c @ 237] 
06 0022fc80 7558336a LocalVariableName!wWinMainCRTStartup+0xd [f:\...\crt0.c @ 165] 
07 0022fc8c 771198f2 kernel32!BaseThreadInitThunk+0xe
08 0022fccc 771198c5 ntdll!__RtlUserThreadStart+0x70
09 0022fce4 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> .frame 1
01 0022fb3c 00f97958 LocalVariableName!CLocalVariableNameApp::CLocalVariableNameApp+0x90 [c:\...\localvariablename.cpp @ 38] 
0:000> dv
           this = 0x01637118
        holycow = 0x00445820

请注意,名称atemp是不可见的。

观察 2:变量名称将被限制在它们的范围内。如果要记住所有变量名,则需要跟踪所有函数。

上面是一个调试版本。发布版本不同:

0:000> k
 # ChildEBP RetAddr  
00 005efe04 002a1c18 KERNELBASE!DebugBreak+0x2
01 005efe20 002a1095 LocalVariableName!CLocalVariableNameApp::CLocalVariableNameApp+0x88 [c:\...\localvariablename.cpp @ 39] 
02 005efe24 003c0289 LocalVariableName!`dynamic initializer for 'theApp''+0x5 [c:\...\localvariablename.cpp @ 43] 
03 005efe38 003c01ea LocalVariableName!_initterm+0x29 [f:\...\crt0dat.c @ 954] 
04 005efe48 003bd280 LocalVariableName!_cinit+0x5a [f:\...\crt0dat.c @ 321] 
05 005efe88 7558336a LocalVariableName!__tmainCRTStartup+0xde [f:\...\crt0.c @ 237] 
06 005efe94 771198f2 kernel32!BaseThreadInitThunk+0xe
07 005efed4 771198c5 ntdll!__RtlUserThreadStart+0x70
08 005efeec 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> .frame 1
01 005efe20 002a1095 LocalVariableName!CLocalVariableNameApp::CLocalVariableNameApp+0x88 [c:\...\localvariablename.cpp @ 39] 
0:000> dv
           this = 0x0043f420

请注意,holycow缺少。

观察 3:在发布版本中,可能不需要(优化)变量,因此不存在。

总体结论:不可能将内存地址映射到变量名。

于 2017-12-13T00:25:43.200 回答