Udostępnij za pośrednictwem


Why do I see ExecutionEngineException, StackOverflowException and OutOfMemoryException on the heap when debugging .net applications?

I came back from a long vacation today and I’ve finally caught up with enough emails to do something useful with my day.

As I scanned through my blog email bucket I noticed that I had a lot of emails relating to my last post on dumping .net exceptions in windbg, and most of them asked why they see OutOfMemoryExceptions on the heap, and how to troubleshoot this.

I think I have mentioned this before, but it seems like it is worth mentioning again as it is probably buried deep in some post from way back when…

When you dump out all the exceptions on your .net GC heap (using !dumpheap -type Exception for example) these 3 types of exceptions will always show up, independently of what type of .net process you are debugging.

79330c30        1           72 System.ExecutionEngineException
79330ba0        1           72 System.StackOverflowException
79330b10        1           72 System.OutOfMemoryException

Contrary to what you may believe, this does not necessarily mean that the process has suffered from a stack overflow for example. 

When you run !dumpheap –type Exception, what you are really doing is dumping out any type of object on the GC heap whose name contains the word Exception, not just the ones that are thrown.

These 3 exceptions (ExecutionEngineException, StackOverflowException and OutOfMemoryException) are very special in the sense that it would be impossible to create an object of type OutOfMemoryException when you are in an OOM situation, as that would fail with yet another OOM.  In the same way you can’t create a StackOverflowException object when you are running into a stack overflow as this would require a call to its constructor which is impossible when the stack is overflowing.

To mitigate this, the CLR will generate these 3 exception objects at startup so that it can just throw them whenever the exception occurs.

In short, if you see these on the heap, don’t panic, unless you have some other evidence that they are occurring, they probably aren’t.    

To see if you are really suffering from one, run !threads and you should see if any threads have recently thrown one.   All of these will make the process crash/exit so you shouldn’t really see them unless you are also seeing a crash.  The only one that you might see without a crash is the OOM, but if you do see one when you run !threads or in the event viewer, you are pretty close to a crash so it should be investigated.

If you do see any of these running !threads, check out the post index to find articles related to troubleshooting each of these types of issues.

Have a good one,

Tess

Comments

  • Anonymous
    August 10, 2009
    thanks, I have learned a lot about debugging with your posts, your blog is already in my favorites list.

  • Anonymous
    August 10, 2009
    Would count > 1 also be a necessary and sufficient reason to panic?

  • Anonymous
    August 10, 2009
    Hi Tess, I'm glad you're back and I hope you had a great vacation. It is not entirely true that it would be impossible to create a new instance of OutOfMemoryException in case of OOM. E.g. if you try to create a huge array, the runtime may not be able to honor that and thus throw an OutOfMemoryException. However, since nothing was allocated, you still have plenty of space and you can carry on allocating other stuff. However, since the situation may be that you cannot allocate anything the safe way to go about it is to preallocate the special exceptions, just like the runtime does. Sorry if this seems like splitting hairs. My point is just that OOM may happen due to either no available memory at all or just not enough memory to handle a specific allocation. In the latter case allocations are still possible after the exception (assuming the exception was handled obviously).

  • Anonymous
    August 10, 2009
    Mohit,  yes Brian, agreed, I was a bit categoric saying it was always impossible :)   It is sometimes impossible to generate a new OOM exception when it occurrs :)

  • Anonymous
    August 17, 2009
    Great post, I've wondered this myself and it's nice to know what's actually going on.

  • Anonymous
    April 08, 2010
    The comment has been removed

  • Anonymous
    July 15, 2012
    it's so pitty, I found your blog too late.