一.问题描述

当一个进程的内存异常大时,可能发生了内存泄漏,也可能是内存中相关队列等数据结构长度未作限制。

二.解决思路

如果问题很容易出现,最好是使用umdh工具来进行判断,此工具的使用方法在其帮助手册中有详细介绍,此处不再赘述。
本文中说的是另外一处思路。众所周知,进程中分为代码空间,数据空间,栈,堆等。除了堆之外,其他部分都是基本固定和有上限限制的。堆的空间大小对于64位的进程可以说基本不受限的,因此我们的思路是查看堆中的内容。

三.解决方法

使用windbg attach到进程后,依次执行

0:003> !heap -sNtGlobalFlag enables following debugging aids for new heaps:    stack back tracesLFH Key                   : 0x0000008f4b2ee335Termination on corruption : ENABLED          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast                             (k)     (k)    (k)     (k) length      blocks cont. heap -------------------------------------------------------------------------------------0000000002460000 08000002    1024    432   1024      1     6     1    0      0   LFH0000000000010000 08008000      64      8     64      5     1     1    0      0      0000000000020000 08008000      64     64     64     61     1     1    0      0      00000000001a0000 08001002    1088    256   1088      3     1     2    0      0   LFH00000000040a0000 08001002     512     28    512      0     2     1    0      0      0000000004080000 08001002    1088    332   1088      6     5     2    0      0   LFH-------------------------------------------------------------------------------------0:003> !heap -stat -h 0000000004080000 heap @ 0000000004080000group-by: TOTSIZE max-display: 20    size     #blocks     total     ( %) (percent of total busy bytes)    6608 1 - 6608  (36.24)    4000 1 - 4000  (22.73)    1000 2 - 2000  (11.37)    1001 1 - 1001  (5.68)    b00 1 - b00  (3.91)    2c8 3 - 858  (2.96)    200 4 - 800  (2.84)    401 1 - 401  (1.42)    3ff 1 - 3ff  (1.42)    30a 1 - 30a  (1.08)    178 2 - 2f0  (1.04)    28 11 - 2a8  (0.94)    38 a - 230  (0.78)    220 1 - 220  (0.75)    100 2 - 200  (0.71)    58 5 - 1b8  (0.61)    160 1 - 160  (0.49)    130 1 - 130  (0.42)    30 6 - 120  (0.40)    48 3 - d8  (0.30)0:003> !heap -flt s 401(这个是随机抽选的,当然我写的示例中正好是泄漏了这么大)    _HEAP @ 2460000    _HEAP @ 10000    _HEAP @ 20000    _HEAP @ 1a0000    _HEAP @ 40a0000    _HEAP @ 4080000              HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state        0000000003f907e0 0043 0000  [00]   0000000003f90810    00401 - (busy)0:003> !heap -p -a 0000000003f90810    address 0000000003f90810 found in    _HEAP @ 4080000              HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state        0000000003f907e0 0043 0000  [00]   0000000003f90810    00401 - (busy)        7700cc0d ntdll! ?? ::FNODOBFM::`string'+0x000000000001913b        71048d17 MSVCR100!malloc+0x000000000000005b        71048ddb MSVCR100!operator new+0x000000000000001f        13fa423d7 test!test1+0x0000000000000017        13fa47ed4 test!boost::detail::thread_data<long (__cdecl*)(void)>::run+0x0000000000000014        13fa52e43 test!boost::`anonymous namespace'::thread_start_function+0x0000000000000043        71001d9f MSVCR100!_callthreadstartex+0x0000000000000017        71001e3b MSVCR100!_threadstartex+0x000000000000007f        76e6652d kernel32!BaseThreadInitThunk+0x000000000000000d        76f9c521 ntdll!RtlUserThreadStart+0x000000000000001d

这样就可以定位到申请内存的代码行数(需要注意的是,设置符号文件,并且执行 gflags.exe /i *.exe +ust)

四.后记

1.有时候我们可能没有来得及设置gflags,这时可以查看堆中的内存内容来猜测可能泄漏的地方。
2.heap -s可以执行多次,观测内存增加的堆地址进行分析。