3

tl;dr;: Is my assumption correct that this is a unmanaged memory leak?

I have a .net 4 WPF application crashing with an out-of-memory exception. Taking Memory dumps i need some advice on reading them:

Starting with !address -summary i get

--- Usage Summary ----- RgnCount --------Total Size -------- %ofBusy %ofTotal
unknown                 1863          37b80000 ( 891.500 Mb)  71.62%   43.53%
Free                    415           3233d000 ( 803.238 Mb)           39.22%
Image                   1542          10327000 ( 259.152 Mb)  20.82%   12.65%
Heap                    83             493e000 (  73.242 Mb)   5.88%    3.58%
Stack                   67             1480000 (  20.500 Mb)   1.65%    1.00%
Other                   12               37000 ( 220.000 kb)   0.02%    0.01%
TEB                     22               16000 (  88.000 kb)   0.01%    0.00%
PEB                     1                 1000 (   4.000 kb)   0.00%    0.00%
--- Type Summary (for busy) -- RgnCount ---------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE                    900            30b7e000 ( 779.492 Mb)  62.62%   38.06%
MEM_IMAGE                      2619           157c3000 ( 343.762 Mb)  27.62%   16.79%
MEM_MAPPED                     71              7972000 ( 121.445 Mb)   9.76%    5.93%
--- State Summary ---------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_COMMIT                   2874              43753000 (   1.054 Gb)  86.71%   52.70%
MEM_FREE                     415               3233d000 ( 803.238 Mb)           39.22%
MEM_RESERVE                  716                a560000 ( 165.375 Mb)  13.29%    8.08%
--- Protect Summary (for commit) - RgnCount ---- Total Size --- %ofBusy %ofTotal
PAGE_READWRITE                    1004       26c48000 ( 620.281 Mb)  49.83%   30.29%
PAGE_EXECUTE_READ                 302        10f1e000 ( 271.117 Mb)  21.78%   13.24%
PAGE_READONLY                     812         7044000 ( 112.266 Mb)   9.02%    5.48%
PAGE_READWRITE|PAGE_WRITECOMBINE  8           22e6000 (  34.898 Mb)   2.80%    1.70%
PAGE_WRITECOPY                    370         1ebf000 (  30.746 Mb)   2.47%    1.50%
PAGE_EXECUTE_READWRITE            238          717000 (   7.090 Mb)   0.57%    0.35%
PAGE_EXECUTE_WRITECOPY            96           287000 (   2.527 Mb)   0.20%    0.12%
PAGE_READWRITE|PAGE_GUARD         44            66000 ( 408.000 kb)   0.03%    0.02%
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
unknown                                    2150000           186e000 (  24.430 Mb)
Free                                      77ffd000           6efb000 ( 110.980 Mb)
Image                                     68d43000            f1e000 (  15.117 Mb)
Heap                                      3c78c000            e04000 (  14.016 Mb)
Stack                                      2050000             fd000 (1012.000 kb)
Other                                     7efb0000             23000 ( 140.000 kb)
TEB                                       7eefa000              1000 (   4.000 kb)
PEB                                       7efde000              1000 (   4.000 kb)

Running !eeheap i get GC Heap size with

GC Heap Size: Size: 0x1f796cdc (528051420) bytes.

Am I correct: total process Memory is mem_commit + mem_free + mem_reserve totaling up to ~2 GB, while managed Memory only uses 500 GB, so I´m facing a native Memory leak?

Onel Sarmiento
  • 1,608
  • 3
  • 20
  • 46
Dominik
  • 3,342
  • 1
  • 17
  • 24

1 Answers1

3

The meaning of Free

Usage Summary's Free and MEM_FREE mean exactly that: the memory is free and can be allocated. It has not been allocated by .NET and it has not been allocated by native code so far.

However, you can even get an OutOfMemoryException with 2 GB of free memory, e.g. by doing

byte[] oops = new byte[Int.MaxValue];

So the question is: how much memory was tried to be allocated vs. how much memory is free at that time?

Fragmentation

Looking at Free or MEM_FREE is not enough, especially if you want to allocate arrays of objects, which are put in sequence one behind another. In this case, there must be enough memory in a single block.

So you have to look in the section Largest Region by Usage and you find Free with only 110 MB there. So it is not possible for anyone to allocate more than 110 MB of new memory as a single block (neither native, nor .NET).

Just to be precise: this does not necessarily mean you cannot allocate 110 MB at all. It could be possible with the help of old memory, e.g. .NET could do a garbage collection, find out that there are 120 MB free and use that instead of asking for 110 MB of new memory.

Final answer

Unfortunately, with the information given, it's not possible to tell the exact reason. You might want to follow my flowchart for OutOfMemoryException analysis and read the question How to identify array type, which also gives an insight on how to identify the array size from a dump file.

Community
  • 1
  • 1
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222