How to debug heap corruption errors?

2019-01-01 04:22发布

I am debugging a (native) multi-threaded C++ application under Visual Studio 2008. On seemingly random occasions, I get a "Windows has triggered a break point..." error with a note that this might be due to a corruption in the heap. These errors won't always crash the application right away, although it is likely to crash short after.

The big problem with these errors is that they pop up only after the corruption has actually taken place, which makes them very hard to track and debug, especially on a multi-threaded application.

  • What sort of things can cause these errors?

  • How do I debug them?

Tips, tools, methods, enlightments... are welcome.

14条回答
时光乱了年华
2楼-- · 2019-01-01 05:04

The best tool I found useful and worked every time is code review (with good code reviewers).

Other than code review, I'd first try Page Heap. Page Heap takes a few seconds to set up and with luck it might pinpoint your problem.

If no luck with Page Heap, download Debugging Tools for Windows from Microsoft and learn to use the WinDbg. Sorry couldn't give you more specific help, but debuging multi-threaded heap corruption is more an art than science. Google for "WinDbg heap corruption" and you should find many articles on the subject.

查看更多
大哥的爱人
3楼-- · 2019-01-01 05:06

You can detect a lot of heap corruption problems by enabling Page Heap for your application . To do this you need to use gflags.exe that comes as a part of Debugging Tools For Windows

Run Gflags.exe and in the Image file options for your executable, check "Enable Page Heap" option.

Now restart your exe and attach to a debugger. With Page Heap enabled, the application will break into debugger whenever any heap corruption occurs.

查看更多
牵手、夕阳
4楼-- · 2019-01-01 05:06

What type of allocation functions are you using? I recently hit a similar error using the Heap* style allocation functions.

It turned out that I was mistakenly creating the heap with the HEAP_NO_SERIALIZE option. This essentially makes the Heap functions run without thread safety. It's a performance improvement if used properly but shouldn't ever be used if you are using HeapAlloc in a multi-threaded program [1]. I only mention this because your post mentions you have a multi-threaded app. If you are using HEAP_NO_SERIALIZE anywhere, delete that and it will likely fix your problem.

[1] There are certain situations where this is legal, but it requires you to serialize calls to Heap* and is typically not the case for multi-threaded programs.

查看更多
旧人旧事旧时光
5楼-- · 2019-01-01 05:06

I'd like to add my experience. In the last few days, I solved an instance of this error in my application. In my particular case, the errors in the code were:

  • Removing elements from an STL collection while iterating over it (I believe there are debug flags in Visual Studio to catch these things; I caught it during code review)
  • This one is more complex, I'll divide it in steps:
    • From a native C++ thread, call back into managed code
    • In managed land, call Control.Invoke and dispose a managed object which wraps the native object to which the callback belongs.
    • Since the object is still alive inside the native thread (it will remain blocked in the callback call until Control.Invoke ends). I should clarify that I use boost::thread, so I use a member function as the thread function.
    • Solution: Use Control.BeginInvoke (my GUI is made with Winforms) instead so that the native thread can end before the object is destroyed (the callback's purpose is precisely notifying that the thread ended and the object can be destroyed).
查看更多
低头抚发
6楼-- · 2019-01-01 05:07

What sort of things can cause these errors?

Doing naughty things with memory, e.g. writing after the end of a buffer, or writing to a buffer after it's been freed back to the heap.

How do I debug them?

Use an instrument which adds automated bounds-checking to your executable: i.e. valgrind on Unix, or a tool like BoundsChecker (Wikipedia suggests also Purify and Insure++) on Windows.

Beware that these will slow your application, so they may be unusable if yours is a soft-real-time application.

Another possible debugging aid/tool might be MicroQuill's HeapAgent.

查看更多
查无此人
7楼-- · 2019-01-01 05:07

You may also want to check to see whether you're linking against the dynamic or static C runtime library. If your DLL files are linking against the static C runtime library, then the DLL files have separate heaps.

Hence, if you were to create an object in one DLL and try to free it in another DLL, you would get the same message you're seeing above. This problem is referenced in another Stack Overflow question, Freeing memory allocated in a different DLL.

查看更多
登录 后发表回答