Archive for May 23rd, 2010

Models for Memory and Trace Analysis Patterns (Part 2)

Sunday, May 23rd, 2010

We continue our modeling of software behaviour with the ubiquitous Memory Leak (process heap) pattern. Instead of leaking small heap allocations that are easy to debug with user mode stack trace database our model program leaks large heap allocations:

// MemoryLeak-ProcessHeap
// Copyright (c) 2010 Dmitry Vostokov
// GNU GENERAL PUBLIC LICENSE
// http://www.gnu.org/licenses/gpl-3.0.txt

#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
 // create extra 25 heaps initially
 for (int i = 0; i < 25; ++i)
  HeapCreate(0, 0, 0);

 
 // create a heap to leak within
 HANDLE hHeap = HeapCreate(0, 0, 0);

 while (true)
 {
  HeapAlloc(hHeap, 0, 1024*1024);
  Sleep(1000);
 }

 return 0;
}

The program creates extra process heaps to simulate real life heap leaks that usually happen not in a default process heap. Then it slowly leaks 0×100000 bytes every second. The application can be downloaded from here (zip file contains source code, x86 and x64 binaries together with corresponding PDB files):

Download MemoryLeak-ProcessHeap.zip

Here I present the results from x64 Windows Server 2008 R2 but x86 variants (I tested on x86 Vista) should be the same.

First we run the application and save a dump of it after a few seconds (I used Task Manager). Heap statistics shows 9 virtual blocks for the last 0000000001e00000 heap:

0:000> !heap -s
LFH Key                   : 0x000000d529c37801
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast
                            (k)     (k)    (k)     (k) length      blocks cont. heap
————————————————————————————-
00000000002b0000 00000002    1024    164   1024      3     1     1    0      0   LFH
0000000000010000 00008000      64      4     64      1     1     1    0      0     
0000000000020000 00008000      64     64     64     61     1     1    0      0     
0000000000220000 00001002    1088    152   1088      3     2     2    0      0   LFH
0000000000630000 00001002     512      8    512      3     1     1    0      0     
0000000000870000 00001002     512      8    512      3     1     1    0      0     
0000000000ad0000 00001002     512      8    512      3     1     1    0      0     
00000000007e0000 00001002     512      8    512      3     1     1    0      0     
0000000000cc0000 00001002     512      8    512      3     1     1    0      0     
0000000000ed0000 00001002     512      8    512      3     1     1    0      0     
00000000010c0000 00001002     512      8    512      3     1     1    0      0     
00000000005b0000 00001002     512      8    512      3     1     1    0      0     
00000000009f0000 00001002     512      8    512      3     1     1    0      0     
00000000004d0000 00001002     512      8    512      3     1     1    0      0     
0000000000230000 00001002     512      8    512      3     1     1    0      0     
0000000000700000 00001002     512      8    512      3     1     1    0      0     
00000000012d0000 00001002     512      8    512      3     1     1    0      0     
0000000000950000 00001002     512      8    512      3     1     1    0      0     
0000000000b90000 00001002     512      8    512      3     1     1    0      0     
00000000014c0000 00001002     512      8    512      3     1     1    0      0     
0000000000e50000 00001002     512      8    512      3     1     1    0      0     
0000000001020000 00001002     512      8    512      3     1     1    0      0     
00000000016e0000 00001002     512      8    512      3     1     1    0      0     
0000000001940000 00001002     512      8    512      3     1     1    0      0     
0000000001b90000 00001002     512      8    512      3     1     1    0      0     
0000000001200000 00001002     512      8    512      3     1     1    0      0     
0000000000c20000 00001002     512      8    512      3     1     1    0      0     
0000000000db0000 00001002     512      8    512      3     1     1    0      0     
0000000000f50000 00001002     512      8    512      3     1     1    0      0     
Virtual block: 0000000001350000 - 0000000001350000 (size 0000000000000000)
Virtual block: 0000000001540000 - 0000000001540000 (size 0000000000000000)
Virtual block: 0000000001760000 - 0000000001760000 (size 0000000000000000)
Virtual block: 00000000019c0000 - 00000000019c0000 (size 0000000000000000)
Virtual block: 0000000001c10000 - 0000000001c10000 (size 0000000000000000)
Virtual block: 0000000001e80000 - 0000000001e80000 (size 0000000000000000)
Virtual block: 0000000001f90000 - 0000000001f90000 (size 0000000000000000)
Virtual block: 00000000020a0000 - 00000000020a0000 (size 0000000000000000)
Virtual block: 00000000021b0000 - 00000000021b0000 (size 0000000000000000)
0000000001e00000 00001002     512      8    512      3     1     1    9      0     

————————————————————————————-

We then wait for a few minutes and save a memory dump again. Heap statistics clearly shows virtual block leaks because now we 276 of them instead of previous 9 (I skipped most of them in the output below):

0:000> !heap -s
LFH Key                   : 0x000000d529c37801
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast
                            (k)     (k)    (k)     (k) length      blocks cont. heap
————————————————————————————-
00000000002b0000 00000002    1024    164   1024      3     1     1    0      0   LFH
0000000000010000 00008000      64      4     64      1     1     1    0      0     
0000000000020000 00008000      64     64     64     61     1     1    0      0     
0000000000220000 00001002    1088    152   1088      3     2     2    0      0   LFH
0000000000630000 00001002     512      8    512      3     1     1    0      0     
0000000000870000 00001002     512      8    512      3     1     1    0      0     
0000000000ad0000 00001002     512      8    512      3     1     1    0      0     
00000000007e0000 00001002     512      8    512      3     1     1    0      0     
0000000000cc0000 00001002     512      8    512      3     1     1    0      0     
0000000000ed0000 00001002     512      8    512      3     1     1    0      0     
00000000010c0000 00001002     512      8    512      3     1     1    0      0     
00000000005b0000 00001002     512      8    512      3     1     1    0      0     
00000000009f0000 00001002     512      8    512      3     1     1    0      0     
00000000004d0000 00001002     512      8    512      3     1     1    0      0     
0000000000230000 00001002     512      8    512      3     1     1    0      0     
0000000000700000 00001002     512      8    512      3     1     1    0      0     
00000000012d0000 00001002     512      8    512      3     1     1    0      0     
0000000000950000 00001002     512      8    512      3     1     1    0      0     
0000000000b90000 00001002     512      8    512      3     1     1    0      0     
00000000014c0000 00001002     512      8    512      3     1     1    0      0     
0000000000e50000 00001002     512      8    512      3     1     1    0      0     
0000000001020000 00001002     512      8    512      3     1     1    0      0     
00000000016e0000 00001002     512      8    512      3     1     1    0      0     
0000000001940000 00001002     512      8    512      3     1     1    0      0     
0000000001b90000 00001002     512      8    512      3     1     1    0      0     
0000000001200000 00001002     512      8    512      3     1     1    0      0     
0000000000c20000 00001002     512      8    512      3     1     1    0      0     
0000000000db0000 00001002     512      8    512      3     1     1    0      0     
0000000000f50000 00001002     512      8    512      3     1     1    0      0     
Virtual block: 0000000001350000 - 0000000001350000 (size 0000000000000000)
Virtual block: 0000000001540000 - 0000000001540000 (size 0000000000000000)
Virtual block: 0000000001760000 - 0000000001760000 (size 0000000000000000)
Virtual block: 00000000019c0000 - 00000000019c0000 (size 0000000000000000)
[… skipped …]
Virtual block: 00000000131b0000 - 00000000131b0000 (size 0000000000000000)
Virtual block: 00000000132c0000 - 00000000132c0000 (size 0000000000000000)
Virtual block: 00000000133d0000 - 00000000133d0000 (size 0000000000000000)
Virtual block: 00000000134e0000 - 00000000134e0000 (size 0000000000000000)
Virtual block: 00000000135f0000 - 00000000135f0000 (size 0000000000000000)
Virtual block: 0000000013700000 - 0000000013700000 (size 0000000000000000)
Virtual block: 0000000013810000 - 0000000013810000 (size 0000000000000000)
Virtual block: 0000000013920000 - 0000000013920000 (size 0000000000000000)
Virtual block: 0000000013a30000 - 0000000013a30000 (size 0000000000000000)
Virtual block: 0000000013b40000 - 0000000013b40000 (size 0000000000000000)
Virtual block: 0000000013c50000 - 0000000013c50000 (size 0000000000000000)
Virtual block: 0000000013d60000 - 0000000013d60000 (size 0000000000000000)
0000000001e00000 00001002     512      8    512      3     1     1  276      0     

————————————————————————————-

We see that size of these blocks is 0×101000 bytes (with hindsight, extra 1000 is probably bookkeeping info):

0:000> !address 0000000013d60000
 ProcessParametrs 00000000002b1f20 in range 00000000002b0000 00000000002d9000
 Environment 00000000002b1320 in range 00000000002b0000 00000000002d9000
    0000000013d60000 : 0000000013d60000 - 0000000000101000
                    Type     00020000 MEM_PRIVATE
                    Protect  00000004 PAGE_READWRITE
                    State    00001000 MEM_COMMIT
                    Usage    RegionUsageHeap
                    Handle   0000000001e00000

We want to know which thread allocates them and we search for the heap address 0000000001e00000 through virtual memory to find any execution residue on thread raw stacks:

0:000> s -q 0 LFFFFFF 0000000001e00000
00000000`001cf608  00000000`01e00000 00000000`01e00000
00000000`001cf610  00000000`01e00000 00000000`00000858
00000000`001cf630  00000000`01e00000 00000000`0000000a
00000000`001cf6c8  00000000`01e00000 00000000`00000000
00000000`001cf6e0  00000000`01e00000 00000000`01e00a80
00000000`001cf720  00000000`01e00000 00000000`00000020
00000000`001cf778  00000000`01e00000 00000000`01e00000
00000000`001cf780  00000000`01e00000 00000000`00000000
00000000`001cf798  00000000`01e00000 00000000`01e02000
00000000`001cf7b0  00000000`01e00000 02100301`00000000
00000000`001cf7c8  00000000`01e00000 00000000`01c10000
00000000`001cf808  00000000`01e00000 00000000`00000001
00000000`001cf830  00000000`01e00000 00000000`00000002
00000000`001cf940  00000000`01e00000 00000000`00000000
00000000`002d8378  00000000`01e00000 004c0044`005c0064
00000000`01e00028  00000000`01e00000 00000000`01e00000
00000000`01e00030  00000000`01e00000 00000000`00000080

Address range 00000000`001cfxxxx belongs to the main thread:

0:000> kL
Child-SP          RetAddr           Call Site
00000000`001cf898 000007fe`fdd91203 ntdll!NtDelayExecution+0xa
00000000`001cf8a0 00000001`3f39104f KERNELBASE!SleepEx+0xab
00000000`001cf940 00000001`3f3911ea MemoryLeak_ProcessHeap!wmain+0×4f
00000000`001cf970 00000000`778cf56d MemoryLeak_ProcessHeap!__tmainCRTStartup+0×15a
00000000`001cf9b0 00000000`77b03281 kernel32!BaseThreadInitThunk+0xd
00000000`001cf9e0 00000000`00000000 ntdll!RtlUserThreadStart+0×1d

We dump the raw stack fragment now:

0:000> dps 00000000`001cf608 00000000`001cf940
00000000`001cf608  00000000`01e00000
00000000`001cf610  00000000`01e00000
00000000`001cf618  00000000`00000858
00000000`001cf620  00000000`00000000
00000000`001cf628  00000000`77b229ac ntdll!RtlAllocateHeap+0×16c
00000000`001cf630  00000000`01e00000
00000000`001cf638  00000000`0000000a
00000000`001cf640  00000000`00000858
00000000`001cf648  00000000`00000860
00000000`001cf650  00000000`00000000
00000000`001cf658  00000000`001cf740
00000000`001cf660  00000020`00001000
00000000`001cf668  fffff680`01000000
00000000`001cf670  00000001`3f390000 MemoryLeak_ProcessHeap!wmain <PERF> (MemoryLeak_ProcessHeap+0×0)
00000000`001cf678  01000000`00000080
00000000`001cf680  00000000`0000f000
00000000`001cf688  02100210`02100210
00000000`001cf690  00000001`3f390000 MemoryLeak_ProcessHeap!wmain <PERF> (MemoryLeak_ProcessHeap+0×0)
00000000`001cf698  00000000`0000f000
00000000`001cf6a0  00000000`01e01fd0
00000000`001cf6a8  00000000`77b07ff3 ntdll!RtlpCreateUCREntry+0xb3
00000000`001cf6b0  00000000`001cf6b8
00000000`001cf6b8  00000000`01e01fc0
00000000`001cf6c0  00000000`00000080
00000000`001cf6c8  00000000`01e00000
00000000`001cf6d0  00000000`00000000
00000000`001cf6d8  00000000`00000a00
00000000`001cf6e0  00000000`01e00000
00000000`001cf6e8  00000000`01e00a80
00000000`001cf6f0  00000000`0007e000
00000000`001cf6f8  00000000`77b0f2bb ntdll!RtlpInitializeHeapSegment+0×19b
00000000`001cf700  00000000`01e00208
00000000`001cf708  00000000`00000000
00000000`001cf710  00000000`01e00230
00000000`001cf718  00000000`00000000
00000000`001cf720  00000000`01e00000
00000000`001cf728  00000000`00000020
00000000`001cf730  00000000`00000000
00000000`001cf738  00000000`77b0f676 ntdll!RtlpInitializeUCRIndex+0×36
00000000`001cf740  000007ff`00000003
00000000`001cf748  00000000`00000100
00000000`001cf750  00000000`00000000
00000000`001cf758  00000000`00001002
00000000`001cf760  00000000`00001002
00000000`001cf768  00000000`77b0fec9 ntdll!RtlCreateHeap+0×8f7
00000000`001cf770  00000000`01e02000
00000000`001cf778  00000000`01e00000
00000000`001cf780  00000000`01e00000
00000000`001cf788  00000000`00000000
00000000`001cf790  03010301`00000000
00000000`001cf798  00000000`01e00000
00000000`001cf7a0  00000000`01e02000
00000000`001cf7a8  00000000`01e80000
00000000`001cf7b0  00000000`01e00000
00000000`001cf7b8  02100301`00000000
00000000`001cf7c0  00000000`001f0000
00000000`001cf7c8  00000000`01e00000
00000000`001cf7d0  00000000`01c10000
00000000`001cf7d8  00000000`01e02000
00000000`001cf7e0  00000000`00270000
00000000`001cf7e8  03020302`00000230
00000000`001cf7f0  00000000`77be7288 ntdll!RtlpInterceptorRoutines
00000000`001cf7f8  00000000`00000000
00000000`001cf800  00000000`00100010
00000000`001cf808  00000000`01e00000
00000000`001cf810  00000000`00000001
00000000`001cf818  00000000`00100000
00000000`001cf820  00000000`00000000
00000000`001cf828  00000000`77b229ac ntdll!RtlAllocateHeap+0×16c
00000000`001cf830  00000000`01e00000
00000000`001cf838  00000000`00000002
00000000`001cf840  00000000`00100000
00000000`001cf848  00000000`00101000
00000000`001cf850  00000000`00000000
00000000`001cf858  00000000`001cf940
00000000`001cf860  00000000`00000000
00000000`001cf868  0000f577`2bd1e0ff
00000000`001cf870  00000000`ffffffff
00000000`001cf878  00000000`10010011
00000000`001cf880  00000000`c00000bb
00000000`001cf888  00000000`00000000
00000000`001cf890  00000000`00000100
00000000`001cf898  000007fe`fdd91203 KERNELBASE!SleepEx+0xab
00000000`001cf8a0  00000000`001cf958
00000000`001cf8a8  00000000`00000000
00000000`001cf8b0  00000000`00000000
00000000`001cf8b8  00000000`00000012
00000000`001cf8c0  ffffffff`ff676980
00000000`001cf8c8  00000000`001cf8c0
00000000`001cf8d0  00000000`00000048
00000000`001cf8d8  00000000`00000001
00000000`001cf8e0  00000000`00000000
00000000`001cf8e8  00000000`00000000
00000000`001cf8f0  00000000`00000000
00000000`001cf8f8  00000000`00000000
00000000`001cf900  00000000`00000000
00000000`001cf908  00000000`00000000
00000000`001cf910  00000000`00000000
00000000`001cf918  00000000`00000000
00000000`001cf920  00000000`00000000
00000000`001cf928  00000000`00000001
00000000`001cf930  00000000`00000000
00000000`001cf938  00000001`3f39104f MemoryLeak_ProcessHeap!wmain+0×4f
00000000`001cf940  00000000`01e00000

We see traces of RtlAllocateHeap but it could be a coincidence (imagine that we don’t have access to source code and can’t do live debugging to put breakpoints). We advise to enable use mode stack trace database as explained for another example process: CTX106970. Then we launch our application again and save a new user dump. We repeat the same procedure to examine the raw stack:

0:000> !heap -s
NtGlobalFlag enables following debugging aids for new heaps:
    stack back traces
LFH Key                   : 0x000000c21e1b31e6
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast
                            (k)     (k)    (k)     (k) length      blocks cont. heap
-------------------------------------------------------------------------------------
0000000001bc0000 08000002    1024    168   1024      5     1     1    0      0   LFH
0000000000010000 08008000      64      4     64      1     1     1    0      0     
0000000000020000 08008000      64     64     64     61     1     1    0      0     
0000000000100000 08001002    1088    152   1088      2     2     2    0      0   LFH
0000000001d90000 08001002     512      8    512      3     1     1    0      0     
0000000001f90000 08001002     512      8    512      3     1     1    0      0     
00000000021c0000 08001002     512      8    512      3     1     1    0      0     
0000000002130000 08001002     512      8    512      3     1     1    0      0     
0000000002370000 08001002     512      8    512      3     1     1    0      0     
0000000001e80000 08001002     512      8    512      3     1     1    0      0     
0000000000110000 08001002     512      8    512      3     1     1    0      0     
0000000002510000 08001002     512      8    512      3     1     1    0      0     
0000000002760000 08001002     512      8    512      3     1     1    0      0     
0000000001cc0000 08001002     512      8    512      3     1     1    0      0     
0000000002030000 08001002     512      8    512      3     1     1    0      0     
0000000002960000 08001002     512      8    512      3     1     1    0      0     
0000000002670000 08001002     512      8    512      3     1     1    0      0     
0000000002b90000 08001002     512      8    512      3     1     1    0      0     
00000000022f0000 08001002     512      8    512      3     1     1    0      0     
00000000028b0000 08001002     512      8    512      3     1     1    0      0     
0000000001f10000 08001002     512      8    512      3     1     1    0      0     
0000000002450000 08001002     512      8    512      3     1     1    0      0     
00000000025f0000 08001002     512      8    512      3     1     1    0      0     
0000000002a40000 08001002     512      8    512      3     1     1    0      0     
0000000002c90000 08001002     512      8    512      3     1     1    0      0     
0000000002d90000 08001002     512      8    512      3     1     1    0      0     
0000000002e80000 08001002     512      8    512      3     1     1    0      0     
0000000002fc0000 08001002     512      8    512      3     1     1    0      0     
00000000030b0000 08001002     512      8    512      3     1     1    0      0     
Virtual block: 0000000003130000 - 0000000003130000 (size 0000000000000000)
Virtual block: 0000000003240000 - 0000000003240000 (size 0000000000000000)
Virtual block: 0000000003350000 - 0000000003350000 (size 0000000000000000)
Virtual block: 0000000003460000 - 0000000003460000 (size 0000000000000000)
Virtual block: 0000000003570000 - 0000000003570000 (size 0000000000000000)
Virtual block: 0000000003680000 - 0000000003680000 (size 0000000000000000)
Virtual block: 0000000003790000 - 0000000003790000 (size 0000000000000000)
Virtual block: 00000000038a0000 - 00000000038a0000 (size 0000000000000000)
Virtual block: 00000000039b0000 - 00000000039b0000 (size 0000000000000000)
Virtual block: 0000000003ac0000 - 0000000003ac0000 (size 0000000000000000)
Virtual block: 0000000003bd0000 - 0000000003bd0000 (size 0000000000000000)
Virtual block: 0000000003ce0000 - 0000000003ce0000 (size 0000000000000000)
0000000002270000 08001002     512      8    512      3     1     1   12      0     

0:000> s -q 0 LFFFFFF 0000000002270000
00000000`0029f648  00000000`02270000 00000000`000000a8
00000000`0029f660  00000000`02270000 00000000`77b99bc7
00000000`0029f6e8  00000000`02270000 00000000`02270000
00000000`0029f6f0  00000000`02270000 00000000`00000858
00000000`0029f710  00000000`02270000 00000000`0000000a
00000000`0029f758  00000000`02270000 00000000`0029f918
00000000`0029f7c0  00000000`02270000 00000000`03ce0040
00000000`0029f858  00000000`02270000 00000000`02270000
00000000`0029f860  00000000`02270000 00000000`00000000
00000000`0029f878  00000000`02270000 00000000`02272000
00000000`0029f890  00000000`02270000 02100301`00000000
00000000`0029f8f8  00000000`02270000 00000000`03ce0040
00000000`0029fa20  00000000`02270000 00000000`00000000
00000000`01be8a08  00000000`02270000 0064006e`00690057
00000000`02270028  00000000`02270000 00000000`02270000
00000000`02270030  00000000`02270000 00000000`00000080

0:000> dqs 00000000`0029f648 00000000`0029fa20
00000000`0029f648  00000000`02270000
00000000`0029f650  00000000`000000a8
00000000`0029f658  00000000`00000a80
00000000`0029f660  00000000`02270000
00000000`0029f668  00000000`77b99bc7 ntdll!RtlStdLogStackTrace+0x47
00000000`0029f670  00000000`002a0000
00000000`0029f678  00000000`0000007e
00000000`0029f680  00000000`02270a80
00000000`0029f688  00000000`00000000
00000000`0029f690  00000000`02270208
00000000`0029f698  00070000`77b99bc7
00000000`0029f6a0  00000000`77b6cd8a ntdll! ?? ::FNODOBFM::`string'+0xf35a
00000000`0029f6a8  00000000`77b0fd07 ntdll!RtlCreateHeap+0x56e
00000000`0029f6b0  000007fe`fdd9c6a4 KERNELBASE!HeapCreate+0x54
00000000`0029f6b8  00000001`3faa1030 MemoryLeak_ProcessHeap!wmain+0x30
00000000`0029f6c0  00000001`3faa11ea MemoryLeak_ProcessHeap!__tmainCRTStartup+0x15a
00000000`0029f6c8  00000000`778cf56d kernel32!BaseThreadInitThunk+0xd
00000000`0029f6d0  00000000`77be7288 ntdll!RtlpInterceptorRoutines
00000000`0029f6d8  00000000`00000000
00000000`0029f6e0  00000000`00000860
00000000`0029f6e8  00000000`02270000
00000000`0029f6f0  00000000`02270000
00000000`0029f6f8  00000000`00000858
00000000`0029f700  00000000`00000000
00000000`0029f708  00000000`77b229ac ntdll!RtlAllocateHeap+0x16c
00000000`0029f710  00000000`02270000
00000000`0029f718  00000000`0000000a
00000000`0029f720  00000000`00000858
00000000`0029f728  00000000`00000860
00000000`0029f730  00000000`00000000
00000000`0029f738  00000000`0029f820
00000000`0029f740  00000000`77be7288 ntdll!RtlpInterceptorRoutines
00000000`0029f748  00000000`00000002
00000000`0029f750  00000000`00100030
00000000`0029f758  00000000`02270000
00000000`0029f760  00000000`0029f918
00000000`0029f768  00000000`00000020
00000000`0029f770  00000000`00000002
00000000`0029f778  00000000`00000005
00000000`0029f780  00000000`000750f0
00000000`0029f788  00000000`77ba25b2 ntdll!RtlpRegisterStackTrace+0x92
00000000`0029f790  00000000`000750b8
00000000`0029f798  00000000`00000003
00000000`0029f7a0  00000000`00000000
00000000`0029f7a8  00000000`77ad7a0a ntdll!RtlCaptureStackBackTrace+0x4a
00000000`0029f7b0  00000000`00000002
00000000`0029f7b8  00000000`00100030
00000000`0029f7c0  00000000`02270000
00000000`0029f7c8  00000000`03ce0040
00000000`0029f7d0  00000000`00100020
00000000`0029f7d8  00000000`77ba2eb7 ntdll!RtlpStackTraceDatabaseLogPrefix+0x57
00000000`0029f7e0  00000000`03ce0040
00000000`0029f7e8  00000000`00000000
00000000`0029f7f0  00000000`00100020
00000000`0029f7f8  00000000`000750f0
00000000`0029f800  00000000`77b6ed2d ntdll! ?? ::FNODOBFM::`string’+0×1a81b
00000000`0029f808  00000001`3faa1044 MemoryLeak_ProcessHeap!wmain+0×44
00000000`0029f810  00000001`3faa11ea MemoryLeak_ProcessHeap!__tmainCRTStartup+0×15a
00000000`0029f818  00000000`778cf56d kernel32!BaseThreadInitThunk+0xd
00000000`0029f820  00000000`77b03281 ntdll!RtlUserThreadStart+0×1d

00000000`0029f828  00000000`00000100
00000000`0029f830  00000000`00000000
00000000`0029f838  00000000`08001002
00000000`0029f840  00000000`08001002
00000000`0029f848  00000000`77b0fec9 ntdll!RtlCreateHeap+0×8f7
00000000`0029f850  00000000`02272000
00000000`0029f858  00000000`02270000
00000000`0029f860  00000000`02270000
00000000`0029f868  00000000`00000000
00000000`0029f870  03010301`00000000
00000000`0029f878  00000000`02270000
00000000`0029f880  00000000`02272000
00000000`0029f888  00000000`022f0000
00000000`0029f890  00000000`02270000
00000000`0029f898  02100301`00000000
00000000`0029f8a0  00000000`00001000
00000000`0029f8a8  00000000`77b9a886 ntdll!RtlpSetupExtendedBlock+0xc6
00000000`0029f8b0  00000000`00000000
00000000`0029f8b8  00000000`02272000
00000000`0029f8c0  00000000`000b0000
00000000`0029f8c8  03020302`00000230
00000000`0029f8d0  00000000`77be7288 ntdll!RtlpInterceptorRoutines
00000000`0029f8d8  00000000`00000002
00000000`0029f8e0  00000000`77be7288 ntdll!RtlpInterceptorRoutines
00000000`0029f8e8  00000000`00000002
00000000`0029f8f0  00000000`00100030
00000000`0029f8f8  00000000`02270000
00000000`0029f900  00000000`03ce0040
00000000`0029f908  00000000`77b6ed6a ntdll! ?? ::FNODOBFM::`string’+0×1a858
00000000`0029f910  00000000`00000000
00000000`0029f918  00000000`00000000
00000000`0029f920  00000000`00100000
00000000`0029f928  00000000`00101000
00000000`0029f930  00000000`00000020
00000000`0029f938  00000000`00000002
00000000`0029f940  00000000`00000000
00000000`0029f948  0000f569`df709780
00000000`0029f950  00000000`ffffffff
00000000`0029f958  00000000`12010013
00000000`0029f960  00000000`c00000bb
00000000`0029f968  00000000`00000000
00000000`0029f970  00000000`00000100
00000000`0029f978  000007fe`fdd91203 KERNELBASE!SleepEx+0xab
00000000`0029f980  00000000`0029fa38
00000000`0029f988  00000000`00000000
00000000`0029f990  00000000`00000000
00000000`0029f998  00000000`00000012
00000000`0029f9a0  ffffffff`ff676980
00000000`0029f9a8  00000000`0029f9a0
00000000`0029f9b0  00000000`00000048
00000000`0029f9b8  00000000`00000001
00000000`0029f9c0  00000000`00000000
00000000`0029f9c8  00000000`00000000
00000000`0029f9d0  00000000`00000000
00000000`0029f9d8  00000000`00000000
00000000`0029f9e0  00000000`00000000
00000000`0029f9e8  00000000`00000000
00000000`0029f9f0  00000000`00000000
00000000`0029f9f8  00000000`00000000
00000000`0029fa00  00000000`00000000
00000000`0029fa08  00000000`00000001
00000000`0029fa10  00000000`00000000
00000000`0029fa18  00000001`3faa104f MemoryLeak_ProcessHeap!wmain+0×4f
00000000`0029fa20  00000000`02270000

Now we see this stack trace fragment from user mode stack trace database on the raw stack shown above:

00000000`0029f800  00000000`77b6ed2d ntdll! ?? ::FNODOBFM::`string'+0x1a81b
00000000`0029f808  00000001`3faa1044MemoryLeak_ProcessHeap!wmain+0×44
00000000`0029f810  00000001`3faa11ea MemoryLeak_ProcessHeap!__tmainCRTStartup+0×15a
00000000`0029f818  00000000`778cf56d kernel32!BaseThreadInitThunk+0xd
00000000`0029f820  00000000`77b03281 ntdll!RtlUserThreadStart+0×1d

And it looks like HeapAlloc was called from wmain indeed with 0×100000 parameter:

0:000> ub 00000001`3faa1044
MemoryLeak_ProcessHeap!wmain+0x26:
00000001`3faa1026 xor     edx,edx
00000001`3faa1028 xor     ecx,ecx
00000001`3faa102a call    qword ptr [MemoryLeak_ProcessHeap!_imp_HeapCreate (00000001`3faa7000)]
00000001`3faa1030 mov     rbx,rax
00000001`3faa1033 xor     edx,edx
00000001`3faa1035 mov     r8d,100000h
00000001`3faa103b mov     rcx,rbx
00000001`3faa103e call    qword ptr [MemoryLeak_ProcessHeap!_imp_HeapAlloc (00000001`3faa7008)]

0:000> dps 00000001`3faa7008 L1
00000001`3faa7008  00000000`77b21b70 ntdll!RtlAllocateHeap

The stack trace fragment from x86 Vista user dump even more straightforward:

0040fa00 77946e0c ntdll!RtlAllocateHeap+0×1e3
0040fa04 0022103a MemoryLeak_ProcessHeap!wmain+0×3a

0040fa08 7677d0e9 kernel32!BaseThreadInitThunk+0xe
0040fa0c 779219bb ntdll!__RtlUserThreadStart+0×23
0040fa10 7792198e ntdll!_RtlUserThreadStart+0×1b
0040fa14 7798924f ntdll!RtlpLogCapturedStackTrace+0×103

Of course, we could simply disassemble wmain after identifying our thread but in real life functions are longer and leaking allocations could have happened from frames not present on current stack traces.

- Dmitry Vostokov @ DumpAnalysis.org + TraceAnalysis.org -