Native Memory Leak Diagnostics with Visual Studio 2015

December 1, 2014

15 comments

The Current Landscape of Native Memory Diagnostics

Leak diagnostics is a nasty business in native applications. There have been many attempts at solving this problem automatically. To name a few:

  • The CRT Debug Heap (which is no longer used by default in Visual Studio 2015! – See update below.) can help identify memory leaks by associating each allocation with additional data on the allocating source file and line number. At program exit (or whenever a special CRT function is called), all blocks that haven’t been freed are printed out. This has been around forever. The problem is that you need to compile with the CRT debug heap enabled, so you can’t pick an arbitrary application and start analyzing it for memory leaks. It’s still a useful technique, and one used by Boost Test. If you’re interested, here’s a great walkthrough.
    UPDATE: Where would I be without you, dear readers! Ofek Shilon points out that it’s the Windows debug heap that’s being phased out by default in Visual Studio 2015, and not the CRT Debug Heap, which is still alive and kicking. Here’s his post on the subject.
  • UMDH (from the Debugging Tools for Windows) can diagnose memory leaks by using built-in Windows support for capturing allocation stack traces. When properly configured, the Windows heap manager will keep track of all outstanding allocations and their stack traces, and umdh.exe can compare allocation snapshots as the program is executing and determine which blocks haven’t been freed. Unlike the CRT debug heap, you get a call stack for each leaking allocation, and you get aggregation so if you leaked 1,000 blocks from a single source location, you only see it once in the report. Moreover, unlike the CRT debug heap, you don’t need any ahead-of-time preparation. You can use UMDH to diagnose any application without recompiling.
  • The Windows heap manager is instrumented with ETW events (HeapAlloc/HeapRealloc/HeapFree), and WPA can aggregate them to show you blocks that were allocated but not freed during a particular trace you record. If you enable stack walking, you can get allocation call stacks as well. Again, just like UMDH, this doesn’t require ahead-of-time preparation and works with optimizations enabled.

I think the key problem with all the approaches above is the amount of configuration they require. Most C++ developers want leak analysis to be available in their IDE, and get the information at their fingertips without running an additional tool and subjecting themselves to complex trace analysis. (UMDH reports are known for being user-unfriendly, and WPA has its quirks as well.)

Native Memory Leak Diagnostics in Visual Studio 2015

Visual Studio 2015 makes native leak analysis a lot easier for most developers. You will still need UMDH or ETW for production debugging and leak detection, but in the comfort of your development workstation, Visual Studio should be able to suit your needs. Basically, you recompile with the Visual C++ 2015 compiler, and then run your app with or without the debugger with the new Diagnostic Tools mode enabled (you can get there using the Alt+F2 keyboard shortcut). To get this working while debugging, you will need to configure a special registry key. This requirement will hopefully go away at RTM, but for now you can find the instructions here.

While the tools are running, you get a nice graph of memory utilization and can capture heap snapshots. You can see right away how many bytes you’re leaking and how many individual allocations they are coming from. In this case, over a span of just a few seconds we leaked over 2.5MB of memory.

Diagnostic tools showing memory accumulation and heap snapshot details

If you pick a specific snapshot, you can see details on what types are in that snapshot and how much memory is taken by objects of each type.

Individual heap snapshot listing types, counts, and sizes

Heap snapshots can be compared, producing easy to read information on which types of allocations are likely leaking. Looks like we have arrays of CPU_INFO_INTERNAL and objects of BATTERY_INFO_INTERNAL taking up lots of memory. All other types line up with no count delta.

Diffing heap snapshots shows which types are likely leaking

And finally, you can dive in and see a list of all objects of a particular type, including their contents and where each individual object was allocated. This is probably the killer feature — you can look at the actual object contents if you like. That’s not something you get out of ETW or UMDH. You can also double click frames on the allocation call stack to jump to the source code.

Object details with allocating call stack and memory contents

It’s worth reiterating that this works with optimizations enabled. The screenshots above were produced using an optimized version. It does have an effect on call stack accuracy if frames are being inlined. In the preceding screenshot, the call stack appears as though TemperatureAndBatteryUpdaterThread called operator new directly. In fact, it called a constructor for a type called BatteryInformation, which isn’t visible in the call stack because it was inlined. (You might expect the /Zo switch to make a difference, but presently it doesn’t. I’ll be sure to check future versions for better inline debugging support.)

Wrap Up

Visual Studio 2015 has really nice native memory debugging support. You can capture heap snapshots, compare them, and get to the bottom of memory leaks by looking at diffs and inspecting individual objects and their allocating call stacks. This experience is much more friendly than anything previously available (CRT debug heap, UMDH, ETW) and will make leak analysis more streamlined for all native developers.


I am posting short links and updates on Twitter as well as on this blog. You can follow me:聽@goldshtn

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

15 comments

  1. OfekDecember 1, 2014 讘 11:27 PM

    Sasha – thanks for a great write up.
    1) Maybe I missed something, but it seems VS2015 won’t show stacks. Looking into the contents is some sort of mitigation, but more often than not there would be no string members or others that could help pinpoint the leak cause.
    2) the CRT debug heap *is* still on by default. The change that did take place is turning off the *Windows* debug heap by default – and IIUC, because it is mostly overlapping in functionality to the CRT debug heap. Here it is in more words.
    3) I read long ago that xperf, WPT’s predecessor, was not the right tool for handling leaks. Did it get better since? Maybe you’d be willing to post a demo of ETW usage for leak detection with WPA?

    Reply
    1. Sasha Goldshtein
      Sasha GoldshteinDecember 2, 2014 讘 12:34 PM

      1) Visual Studio 2015 Preview shows stacks for me. You can see it in the last screenshot.
      2) Whoops! Thanks a lot for pointing that out. I will update the post. Obviously I got a little carried away 馃檪
      3) I used WPA many times for detecting heap leaks. You just need to capture the trace over the right period of time and look at AIFO allocations. Works pretty reliably. I will definitely consider posting a quick writeup about it.

      Reply
    2. Sasha Goldshtein
      Sasha GoldshteinDecember 2, 2014 讘 12:34 PM

      By the way, could it be you’re not getting stacks because you’re on 64-bit? I think that’s a temporary limitation in the Preview.

      Reply
      1. OfekDecember 3, 2014 讘 6:27 PM

        Thanks for the reply and the new post! I’ll re-test VS2015 soon.

        Reply
  2. Pingback: Diagnosing Native Memory Leaks with ETW and WPA

  3. Marc ShermanDecember 2, 2014 讘 5:56 PM

    Awesome writeup, thanks!

    Reply
  4. Mike GDecember 3, 2014 讘 12:46 AM

    Hi!

    Would it show GDI leaks, or leaks made by COM calls like SysAllocString?

    Reply
    1. Sasha Goldshtein
      Sasha GoldshteinDecember 12, 2014 讘 11:59 AM

      No, I believe it is limited to standard C/C++ heap allocations.

      Reply
  5. Milos TosicMarch 14, 2015 讘 5:27 AM

    Memory profiling and leak detection for native applications can be performed with ease using MTunerhttp://www.mtuner.net

    Reply
    1. Sasha Goldshtein
      Sasha GoldshteinMarch 19, 2015 讘 2:06 PM

      That’s a nice tool, but as far as I can tell it doesn’t tell you the type of each heap object and doesn’t let you explore the object’s contents. These are two features Visual Studio 2015 will have, which are extremely nice.

      Reply
  6. Pingback: C++ Daily 2015-08-23 | blog.vladon.com

  7. Tarmo PikaroFebruary 15, 2016 讘 11:26 PM

    How about this memory leak detection tool:
    http://www.saunalahti.fi/~tarmpika/diagnostic/
    ?

    Gets statistics on leaked memory without recompilation, and moreover ordered from developer perspective (who leaked and how much)

    Reply
  8. DimaAugust 10, 2016 讘 3:25 PM

    Will this also help track leaking COM objects?

    Reply
    1. Sasha Goldshtein
      Sasha GoldshteinDecember 21, 2016 讘 11:04 AM

      If they are allocated with the instrumented allocators, then yes.

      Reply
  9. Tarmo PikaroOctober 22, 2016 讘 9:05 PM

    Hi !

    Here is my own tool for memory leak detection:

    https://sourceforge.net/projects/diagnostic/

    Besides being high performance, it does not require any code recompilation, and works out of box. Besides showing exact callstacks it will also display how much memory is lost.

    Open source code, contributors are welcomed.

    Reply