Memory leak in WinDBG?

My machine is running Win7 SP1 x64 and has 16 Gb physical memory.
I am tracking down large memory allocations in my user application, which
mostly processes MSSQL records.

What I normally do is to attach WinDBG, set a breakpoint on RtlAllocateHeap
and log the stack each time the allocation is larger than 64Kb.
My application is 32 bits, so I normally use WinDBG x86 version

CMD> *Windbg -WX -Q -loga %TEMP%\dump_bat_windbg_session_32.log -pn
S3DHost.exe*

I then create a break point that prints the stack, but only if the

allocation is larger than 64Kb:
*bp ntdll!RtlAllocateHeap “j (poi(@esp+0xc)>=0x10000) ‘kvn15;gc’ ; ‘gc’”*
*g*

stack prints every time allocation request is larger than 64Kb

As you can imagine, RtlAllocateHeap is called frequently.

The problem I have encountered is that WinDBG is leaking memory, about
114Kb / 4 seconds (TaskManager Low speed update).

WinDBG private memory goes all the way close to 4Gb then a dialog prompts
to stop WinDBG.
I ended up with a partial report. At least I know where

I then repeated the whole process using WinDBG x64.
In this case there will be two ntdlls loaded to the process, the
system32\ntdll.dll (the 64 bit) and the sysWow64\ntdll.dll (the 32 bit
shim).
Notice that I switch to debugging the Wow64 by using initialization
commands on the cmd line.

CMD> *Windbg -WX -Q -loga %TEMP%\dump_bat_windbg_session_64.log -c “.load
wow64exts;!wow64exts.sw” -pn S3DHost.exe*
0:013:x86> *lmvm ntdll*
*start end module name
77590000 77739000 *ntdll* (pdb symbols)
c:\symbolcache\ntdll.pdb\15EB43E23B12409C84E3CC7635BAF5A32\ntdll.pdb
Loaded symbol image file: C:\Windows\SYSTEM32\ntdll.dll
Image path: C:\Windows\SYSTEM32\ntdll.dll
Image name: ntdll.dll
Timestamp: Thu Nov 17 00:32:46 2011 (4EC4AA8E)
CheckSum: 001AC7EE
ImageSize: 001A9000
File version: 6.1.7601.17725
Product version: 6.1.7601.17725
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft? Windows? Operating System
InternalName: ntdll.dll
OriginalFilename: ntdll.dll
ProductVersion: 6.1.7601.17725
FileVersion: 6.1.7601.17725 (win7sp1_gdr.111116-1503)
FileDescription: NT Layer DLL
LegalCopyright: ? Microsoft Corporation. All rights reserved.
77770000 778f0000 *ntdll_77770000* (deferred)
Image path: ntdll.dll
Image name: ntdll.dll
Timestamp: Wed Nov 16 23:28:47 2011 (4EC49B8F)
CheckSum: 0014909F
ImageSize: 00180000
File version: 6.1.7601.17725
Product version: 6.1.7601.17725
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft? Windows? Operating System
InternalName: ntdll.dll
OriginalFilename: ntdll.dll
ProductVersion: 6.1.7601.17725
FileVersion: 6.1.7601.17725 (win7sp1_gdr.111116-1503)
FileDescription: NT Layer DLL
LegalCopyright: ? Microsoft Corporation. All rights reserved.

I then create a break point that prints the stack, but only if the

allocation is larger than 64Kb:

0:013:x86> *bp ntdll_77770000!RtlAllocateHeap “j (poi(@esp+0xc)>=0x10000)
‘kvn15;gc’ ; ‘gc’”
*0:013:x86> *g*

stack prints every time allocation request is larger than 64Kb, in this

case 66,160 bytes (0x*10270*)

ChildEBP RetAddr Args to Child

00 0084c0cc 750a9d45 00990000 00000000
*00010270*ntdll_77770000!RtlAllocateHeap (FPO: [Non-Fpo])
01 0084c0ec 750ab0d7 *00010270* 65262cd0 0084c128 msvcrt!malloc+0x8d (FPO:
[Non-Fpo])
02 0084c0fc 6526f083 *00010270* 354e945b 751dca78 msvcrt!operator new+0x1d
(FPO: [Non-Fpo])
03 0084c128 6526c471 00000000 159c7e60 00000000
ASYCFILT!CGIFFilter::Create+0x16 (FPO: [Non-Fpo])
04 0084c13c 7520c68c 751dca68 00000000 00000001
ASYCFILT!FilterCreateInstance+0x3e (FPO: [Non-Fpo])
05 0084c190 751dca11 751dca68 15ae4aa8 159c7e60
OLEAUT32!_PictLoadSyncImage+0x3b (FPO: [Non-Fpo])
06 0084c1c4 751c43a2 15ae4aa8 159c4947 0000108a
OLEAUT32!_PictLoadNewImage+0x173 (FPO: [Non-Fpo])
07 0084c1ec 75207100 15ae4aa8 159c7e60 00000000
OLEAUT32!_PictLoadPicture+0x25 (FPO: [Non-Fpo])
08 0084c21c 75207c57 159c7e60 00000000 00000000
OLEAUT32!OleLoadPictureEx+0x6f (FPO: [Non-Fpo])
09 0084c244 6798a72c 159c7e60 00000000 00000000
OLEAUT32!OleLoadPicture+0x1e (FPO: [Non-Fpo])
0a 0084c2b8 687b3bba 00000000 00000000 0d0021b0
PartDefOleDb!CCJPOPartClassODB::RestoreInstanceData+0x71c (FPO: [1,19,0])
(CONV: thiscall)
[*m:\refdata\middle\entities\partdef\oledb\cjpopartclassodb.cpp
@ 543*]
.
.
.

WinDBG x64 Working Set Memory in TaskManager grows to ~12Gb in size, then
the same dialog shows up asking to finish it due to low system memory.
The only way to get a complete log is to run the process over and over and
start logging at the count where processing stopped the previous time, then
merge the log files for each run to get a complete scenario report.

Do you guys have any suggestions on how to accomplish my memory logging but
avoid the memory leaks?

Appreciate any input,
Osiris Pedroso

Have you narrowed down what causes the leak at all? The most obvious cause
would possibly be the log, if you run without a log does the memory increase
still happen? (This doesn’t help you with a solution of course, but it paves
the way for a workaround.)

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Osiris Pedroso” wrote in message news:xxxxx@windbg…
My machine is running Win7 SP1 x64 and has 16 Gb physical memory.
I am tracking down large memory allocations in my user application, which
mostly processes MSSQL records.

What I normally do is to attach WinDBG, set a breakpoint on RtlAllocateHeap
and log the stack each time the allocation is larger than 64Kb.
My application is 32 bits, so I normally use WinDBG x86 version

CMD> Windbg -WX -Q -loga %TEMP%\dump_bat_windbg_session_32.log -pn
S3DHost.exe

# I then create a break point that prints the stack, but only if the
allocation is larger than 64Kb:
bp ntdll!RtlAllocateHeap “j (poi(@esp+0xc)>=0x10000) ‘kvn15;gc’ ; ‘gc’”
g
# stack prints every time allocation request is larger than 64Kb

As you can imagine, RtlAllocateHeap is called frequently.

The problem I have encountered is that WinDBG is leaking memory, about 114Kb
/ 4 seconds (TaskManager Low speed update).

WinDBG private memory goes all the way close to 4Gb then a dialog prompts to
stop WinDBG.
I ended up with a partial report. At least I know where

I then repeated the whole process using WinDBG x64.
In this case there will be two ntdlls loaded to the process, the
system32\ntdll.dll (the 64 bit) and the sysWow64\ntdll.dll (the 32 bit
shim).
Notice that I switch to debugging the Wow64 by using initialization commands
on the cmd line.

CMD> Windbg -WX -Q -loga %TEMP%\dump_bat_windbg_session_64.log -c “.load
wow64exts;!wow64exts.sw” -pn S3DHost.exe
0:013:x86> lmvm ntdll*
start end module name
77590000 77739000 ntdll (pdb symbols)
c:\symbolcache\ntdll.pdb\15EB43E23B12409C84E3CC7635BAF5A32\ntdll.pdb
Loaded symbol image file: C:\Windows\SYSTEM32\ntdll.dll
Image path: C:\Windows\SYSTEM32\ntdll.dll
Image name: ntdll.dll
Timestamp: Thu Nov 17 00:32:46 2011 (4EC4AA8E)
CheckSum: 001AC7EE
ImageSize: 001A9000
File version: 6.1.7601.17725
Product version: 6.1.7601.17725
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: ntdll.dll
OriginalFilename: ntdll.dll
ProductVersion: 6.1.7601.17725
FileVersion: 6.1.7601.17725 (win7sp1_gdr.111116-1503)
FileDescription: NT Layer DLL
LegalCopyright: © Microsoft Corporation. All rights reserved.
77770000 778f0000 ntdll_77770000 (deferred)
Image path: ntdll.dll
Image name: ntdll.dll
Timestamp: Wed Nov 16 23:28:47 2011 (4EC49B8F)
CheckSum: 0014909F
ImageSize: 00180000
File version: 6.1.7601.17725
Product version: 6.1.7601.17725
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: ntdll.dll
OriginalFilename: ntdll.dll
ProductVersion: 6.1.7601.17725
FileVersion: 6.1.7601.17725 (win7sp1_gdr.111116-1503)
FileDescription: NT Layer DLL
LegalCopyright: © Microsoft Corporation. All rights reserved.

# I then create a break point that prints the stack, but only if the
allocation is larger than 64Kb:

0:013:x86> bp ntdll_77770000!RtlAllocateHeap “j (poi(@esp+0xc)>=0x10000)
‘kvn15;gc’ ; ‘gc’”
0:013:x86> g
# stack prints every time allocation request is larger than 64Kb, in this
case 66,160 bytes (0x10270)
# ChildEBP RetAddr Args to Child
00 0084c0cc 750a9d45 00990000 00000000 00010270
ntdll_77770000!RtlAllocateHeap (FPO: [Non-Fpo])
01 0084c0ec 750ab0d7 00010270 65262cd0 0084c128 msvcrt!malloc+0x8d (FPO:
[Non-Fpo])
02 0084c0fc 6526f083 00010270 354e945b 751dca78 msvcrt!operator new+0x1d
(FPO: [Non-Fpo])
03 0084c128 6526c471 00000000 159c7e60 00000000
ASYCFILT!CGIFFilter::Create+0x16 (FPO: [Non-Fpo])
04 0084c13c 7520c68c 751dca68 00000000 00000001
ASYCFILT!FilterCreateInstance+0x3e (FPO: [Non-Fpo])
05 0084c190 751dca11 751dca68 15ae4aa8 159c7e60
OLEAUT32!_PictLoadSyncImage+0x3b (FPO: [Non-Fpo])
06 0084c1c4 751c43a2 15ae4aa8 159c4947 0000108a
OLEAUT32!_PictLoadNewImage+0x173 (FPO: [Non-Fpo])
07 0084c1ec 75207100 15ae4aa8 159c7e60 00000000
OLEAUT32!_PictLoadPicture+0x25 (FPO: [Non-Fpo])
08 0084c21c 75207c57 159c7e60 00000000 00000000
OLEAUT32!OleLoadPictureEx+0x6f (FPO: [Non-Fpo])
09 0084c244 6798a72c 159c7e60 00000000 00000000 OLEAUT32!OleLoadPicture+0x1e
(FPO: [Non-Fpo])
0a 0084c2b8 687b3bba 00000000 00000000 0d0021b0
PartDefOleDb!CCJPOPartClassODB::RestoreInstanceData+0x71c (FPO: [1,19,0])
(CONV: thiscall)
[m:\refdata\middle\entities\partdef\oledb\cjpopartclassodb.cpp @ 543]
.
.
.

WinDBG x64 Working Set Memory in TaskManager grows to ~12Gb in size, then
the same dialog shows up asking to finish it due to low system memory.
The only way to get a complete log is to run the process over and over and
start logging at the count where processing stopped the previous time, then
merge the log files for each run to get a complete scenario report.

Do you guys have any suggestions on how to accomplish my memory logging but
avoid the memory leaks?

Appreciate any input,
Osiris Pedroso