Click here to Skip to main content
15,880,891 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
We have a windows program that was written in C++ that has a memory leak. We collected a couple of dumps in order to determine where the leak is. My standard method of doing this is to use WinDbg using the !heap -s on the two dumps to find out which heap is growing, then use !heap -stat -h
. The problem is that while I can see a specific heap growing, none of the allocations are growing when I run !heap -stat -h. Historically, this methodology has helped me find out where my memory is leaking, but now it seems to have failed me.Where do I go from here?

What I have tried:

Here is the output of the dump file from the first dump:
0:000> !heap -s


************************************************************************************************************************
                                              NT HEAP STATS BELOW
************************************************************************************************************************
LFH Key                   : 0x7230554a
Termination on corruption : DISABLED
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
005b0000 00000002    8284   5896   8176    137   148     5    6      b   LFH
00830000 00001002    1188    204   1080     27     8     2    0      0   LFH
02bd0000 00001002    1188    128   1080     24     6     2    0      0   LFH
02b90000 00041002      60      4     60      0     1     1    0      0      
03100000 00001002    1188    128   1080     22     6     2    0      0   LFH
05cc0000 00001003      60      8     60      6     1     1    0    N/A   
05dc0000 00001003    1080    124   1080     77    24     2    0    N/A   
05f10000 00001003      60      4     60      2     1     1    0    N/A   
05ef0000 00001003      60      4     60      2     1     1    0    N/A   
060b0000 00001003      60      4     60      2     1     1    0    N/A   
062a0000 00001003      60      4     60      2     1     1    0    N/A   
05d60000 00001003      60      4     60      2     1     1    0    N/A   
06080000 00001003      60      4     60      2     1     1    0    N/A   
05e70000 00001003      60      4     60      2     1     1    0    N/A   
064a0000 00001003      60      4     60      2     1     1    0    N/A   
05c90000 00001003      60      4     60      2     1     1    0    N/A   
05c50000 00001003      60      4     60      2     1     1    0    N/A   
-----------------------------------------------------------------------------

Here is the output of the second file:
0:000> !heap -s


************************************************************************************************************************
                                              NT HEAP STATS BELOW
************************************************************************************************************************
LFH Key                   : 0x7230554a
Termination on corruption : DISABLED
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
005b0000 00000002   81224  68308  81116   1676   474     9    6     15   LFH
00830000 00001002    1188    260   1080     34     6     2    0      0   LFH
02bd0000 00001002    1188    148   1080     28     6     2    0      0   LFH
02b90000 00041002      60      4     60      0     1     1    0      0      
03100000 00001002    1188    148   1080     27     6     2    0      0   LFH
05cc0000 00001003      60      8     60      6     1     1    0    N/A   
05dc0000 00001003    1080    124   1080     62    57     2    0    N/A   
05f10000 00001003      60      4     60      2     1     1    0    N/A   
05ef0000 00001003      60      4     60      2     1     1    0    N/A   
060b0000 00001003      60      4     60      2     1     1    0    N/A   
062a0000 00001003      60      4     60      2     1     1    0    N/A   
05d60000 00001003      60      4     60      2     1     1    0    N/A   
06080000 00001003      60      4     60      2     1     1    0    N/A   
05e70000 00001003      60      4     60      2     1     1    0    N/A   
064a0000 00001003      60      4     60      2     1     1    0    N/A   
05c90000 00001003      60      4     60      2     1     1    0    N/A   
05c50000 00001003      60      4     60      2     1     1    0    N/A   
21430000 00001002    1188     80   1080     18     8     2    0      0   LFH
-----------------------------------------------------------------------------


As you can see, the heap at 005b0000 has grown quite a bit. Now, when I use !heap -stat -h 005b0000 the first dump returns the following:
0:000> !heap -stat -h 005b0000 
 heap @ 005b0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    27c9 25 - 5c00d  (24.26)
    2680 11 - 28e80  (10.78)
    17b0c 1 - 17b0c  (6.25)
    3bc 35 - c5ec  (3.26)
    c da5 - a3bc  (2.70)
    c4 ca - 9aa8  (2.55)
    a0 e4 - 8e80  (2.35)
    8000 1 - 8000  (2.11)
    30 27f - 77d0  (1.97)
    c80 9 - 7080  (1.85)
    24 2d7 - 663c  (1.68)
    1000 5 - 5000  (1.32)
    4e20 1 - 4e20  (1.29)
    4a20 1 - 4a20  (1.22)
    40 10d - 4340  (1.11)
    1048 4 - 4120  (1.07)
    208 20 - 4100  (1.07)
    4040 1 - 4040  (1.06)
    4000 1 - 4000  (1.05)
    2000 2 - 4000  (1.05)


And this is from the second dump file:
0:000> !heap -stat -h 005b0000 
 heap @ 005b0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    27c9 25 - 5c00d  (23.73)
    2680 11 - 28e80  (10.55)
    17b0c 1 - 17b0c  (6.11)
    3bc 32 - bab8  (3.01)
    c e09 - a86c  (2.71)
    c4 ca - 9aa8  (2.49)
    a0 e6 - 8fc0  (2.32)
    8000 1 - 8000  (2.06)
    30 283 - 7890  (1.94)
    c80 9 - 7080  (1.81)
    24 2d8 - 6660  (1.65)
    40 153 - 54c0  (1.37)
    1000 5 - 5000  (1.29)
    4e20 1 - 4e20  (1.26)
    4a20 1 - 4a20  (1.19)
    1048 4 - 4120  (1.05)
    4040 1 - 4040  (1.04)
    4000 1 - 4000  (1.03)
    2000 2 - 4000  (1.03)
    208 1f - 3ef8  (1.02)
Posted
Updated 5-Aug-16 15:10pm
Comments
barneyman 4-Aug-16 18:23pm    
you may need a more pro-active approach - something like VLD https://vld.codeplex.com/ may be useful

You may not have a leak, you may simply be fragmenting the heap?

i generally round the allocation size up to a the nearest para when a have a *lot* of heap hits

I would inspect the code for interesting code pathes in which memory is allocated. Comments them out or run them in loops.

I solved some problems with this tools for Memory Leak Detection.

Sometimes memory allocation is done by system calls like HeapAlloc where you wont find any leaks.

Using the vld or another tools is always a good idea. For deleaker is a trial version available. ;-)
 
Share this answer
 
You should learn to use the debugger as soon as possible. Rather than guessing what your code is doing, It is time to see your code executing and ensuring that it does what you expect.

The debugger allow you to follow the execution line by line, inspect variables and you will see that there is a point where it stop doing what you expect.
Debugger - Wikipedia, the free encyclopedia[^]
Mastering Debugging in Visual Studio 2010 - A Beginner's Guide[^]

The debugger is here to show you what your code is doing and your task is to compare with what it should do.
When the code don't do what is expected, you are close to a bug.

With the debugger, inspect where you allocate some memory and where you free it.
the memory leak is when you allocate some memory to a variable and never free this memory.
You probably loose track of the memory without freeing it first.
 
Share this answer
 
A good old code review might help as well, especially if you can get someone else to look at your code.
A pair of fresh eyes can sometimes detect in minutes, the problems you have been trying to find for hours.

In this case you could focus on memory allocation and memory release only.
Look for all kinds of alloc and make sure you free the memory in all paths of the code.
It is very common to see that memory is not released if the code executes a secondary path or an exception occurs.
It is not unheard of that malloc is called twice and free only once, because the code was written in a hurry or a later addition was made by another person.

Maybe you have done this already, but if not it might be worth a try even if it is a boring thing to do.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900