UMDH is not perfect to analyze native memory leaks in .NET applications
By using UMDH, you can identify the calls that result in the largest leak of native memory. The tool is a perfect killer of native memory leaks in native applications. However, if the native memory leak happens in a .NET application, UMDH is sometimes not that useful because of its incapability to interpret .NET call stack.
Native memory leaks in .NET applications are usually caused by .NET - native interop, thus the stack trace of the culprit calls should include some .NET functions and modules in most cases. Take the following C# code snippet that causes 100K native memory leak as an example.
1: static void Main(string args)
3: Console.ReadLine(); // Take a UMDH log here
4: for (int i = 1; i < 100; i++)
6: Marshal.AllocHGlobal(1000); // Leak 1KB memory
8: Console.ReadLine(); // Take a UMDH log here
If you take UMDH logs at the two Console.ReadLine() positions and compare the logs, you will get this stack trace from UMDH:
+ 182b8 ( 182b8 - 0) 63 allocs BackTrace720EC8
+ 63 ( 63 - 0) BackTrace720EC8 allocations
mscorlib.ni!???+00000000 : 584E5567
mscorlib.ni!???+00000000 : 58968C45
Out of expectation, you do not see any meaning managed calls, such as Marshal.AllocHGlobal and the call of Program.Main, in the UMDH output. The call stack is almost useless to find the culprit .NET code because UMDH cannot walk .NET stacks. If you had dump from the time of the UMDH trace you might be able to retrospectively infer where in the managed code was making the call by doing things like
0:000> !ip2md 584E5567
Method Name: System.Runtime.InteropServices.Marshal.AllocHGlobal(IntPtr)
0:000> !ip2md 58968C45
Method Name: System.Runtime.InteropServices.Marshal.AllocHGlobal(Int32)
There is no method to find the real culprit function in the above example: Program.Main.
If you want more information shared by our team, please follow us @ Twitter