I have a process dump from a Windows 10 64-bit .Net Winforms application that suffered from a System.OutOfMemoryException. The dump file is 1.3GB. A managed profiler (dotMemory) says 220MB of heap is allocated (of which 108MB is used).
The app is compiled as AnyCPU, prefer 32-bit is off. It also contains CLI/C++ projects that target x64, so it just won't run in a 32-bit environment. The app happily uses more than 1.3GB in other circumstances.
It is running on a system with 16GB of RAM, so why does it go out of memory?
The exception stack trace:
System.OutOfMemoryException: Out of memory.
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
at System.Drawing.Graphics.FromHdc(IntPtr hdc)
at DevExpress.XtraBars.Docking2010.DocumentsHost.DoPaint(Message& m)
at DevExpress.XtraBars.Docking2010.DocumentsHost.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Heap fragmentation could be a thing. This is the report from dotMemory (managed mem), nothing to worry about as far as I can see:
WinDbg gives me this for '!address -summary'. Although a lot of , the majority is only 'reserve' and not 'commit'.
0:000> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 405 7ffe`8db96000 ( 127.994 TB) 100.00%
<unknown> 1515 1`3f3b3000 ( 4.988 GB) 86.22% 0.00%
Image 2261 0`25f26000 ( 607.148 MB) 10.25% 0.00%
Heap 120 0`08324000 ( 131.141 MB) 2.21% 0.00%
Stack 234 0`04bc0000 ( 75.750 MB) 1.28% 0.00%
Other 39 0`00200000 ( 2.000 MB) 0.03% 0.00%
TEB 78 0`0009c000 ( 624.000 kB) 0.01% 0.00%
PEB 1 0`00001000 ( 4.000 kB) 0.00% 0.00%
--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE 1882 1`452fe000 ( 5.081 GB) 87.82% 0.00%
MEM_IMAGE 2261 0`25f26000 ( 607.148 MB) 10.25% 0.00%
MEM_MAPPED 105 0`07236000 ( 114.211 MB) 1.93% 0.00%
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE 405 7ffe`8db96000 ( 127.994 TB) 100.00%
MEM_RESERVE 681 1`22426000 ( 4.535 GB) 78.39% 0.00%
MEM_COMMIT 3567 0`50034000 ( 1.250 GB) 21.61% 0.00%
--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READWRITE 1835 0`23d12000 ( 573.070 MB) 9.67% 0.00%
PAGE_EXECUTE_READ 195 0`15090000 ( 336.563 MB) 5.68% 0.00%
PAGE_READONLY 854 0`13fde000 ( 319.867 MB) 5.40% 0.00%
PAGE_WRITECOPY 484 0`01633000 ( 22.199 MB) 0.37% 0.00%
PAGE_EXECUTE_READWRITE 92 0`012db000 ( 18.855 MB) 0.32% 0.00%
PAGE_READWRITE|PAGE_WRITECOMBINE 5 0`00830000 ( 8.188 MB) 0.14% 0.00%
PAGE_READWRITE|PAGE_GUARD 78 0`0015e000 ( 1.367 MB) 0.02% 0.00%
PAGE_NOACCESS 24 0`00018000 ( 96.000 kB) 0.00% 0.00%
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
Free 213`79810000 7de1`2f130000 ( 125.880 TB)
<unknown> 7ff4`a8af0000 1`00020000 ( 4.000 GB)
Image 7ffd`06181000 0`03b43000 ( 59.262 MB)
Heap 213`6b332000 0`0095d000 ( 9.363 MB)
Stack 52`c8600000 0`000fb000 (1004.000 kB)
Other 213`311e0000 0`00181000 ( 1.504 MB)
TEB 52`c8000000 0`00002000 ( 8.000 kB)
PEB 52`c8158000 0`00001000 ( 4.000 kB)
Excessive use of GDI handles is a common cause for trouble, but the application has a watchdog for that: it fails if GDI/user handles reach 8000, well below the 10000 OS limit.
I also found this bug report but it was fixed ages ago.
In this post a typical cause is having Bitmap instances that are not disposed, so their unmanaged memory piles up. But that should show up in the WinDbg output then. Anyway, I've compared the typical use of the application with the faulty behavior, and they both have around 1000 Bitmap instances around (many icons etc). It could still be caused by a few very large undisposed Bitmap's, but that seems unlikely. And it still doesn't explain why it goes out of memory at 1.3GB on a system with 16GB RAM.
What else can be the cause? Memory fragmentation of the unmanaged memory? What can I do to further investigate this issue?