Jump to content
  • Advertisement
Sign in to follow this  
Fire Lancer

Dealing with fatal errors

This topic is 2867 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Generally I use exceptions for error handling, however I have not in my previous projects managed to come up with a solution for handling fatal errors (including SEH exceptions like access violations) in a manner I am happy with.

Ideally Id like to be able to create a user-friendly message for the error (at least ones likely to be caused by invalid data files or other things that non-programmers I am working with may encounter) as well as information more useful to me as a programmer (eg a mini-dump). It would also be useful to have a feature that makes it easy for end-users to report problems (eg a crash dialogue with a "submit report to developers" button or something) including all the information relevant to the error such as a mini dump, the operating system, which version of the program, etc.


However as I said I have been unable to come up with a design that does this to my satisfaction, mainly:

  • If I have try and catches around everything in the main function the stack is unwound before entering the catch block. Although I can still use the exception object itself to create a message to display, the unwinding of the stack has destroyed a lot of the information useful to debugging.

  • I could collect the information for debugging in the constructor of the exception object. However this is not practical for exception classes I did not write, and is also very slow for exceptions that may not be fatal if it creates a dump for every throw.

  • If I don't make any attempt to catch fatal errors, the user gets the standard Windows dialogue to say the program crashed. However to get useful debugging information like a mini dump the user must now do some stuff themselves, which end-users rarely bother to do, normally just complaining that it "doesn't work" if at all.

Share this post


Link to post
Share on other sites
Advertisement
Which compiler are you using? Assuming MSVC, since you mention SEH, you can use the sample code in this article as an example of how to get a stack trace from within an exception filter to handle C++ and SEH exceptions for 32-bit x86.

Share this post


Link to post
Share on other sites
Yes I am using MSVC, I kind of assumed all Windows compilers would have some support however...I guess if people want to handle SEH there then they have to write some inline assembly?

I'll look at that article in more detail in the morning. By the looks of it, it's taking advantage of C++ exceptions being implemented using SEH and that the compiler does not carry out stack unwinding before entering a __catch block filter so everything is still there for a mini dump or stack trace, as well as it being possible to get the c++ exception object in the case of c++ exceptions (and use RTTI to determine it's type)?

What is the reason for it being x86 only, I couldn't see anything when I went through it just now that stood out as not working? Did Microsoft just implement exceptions differently for 64bit applications or something?

Share this post


Link to post
Share on other sites
Exceptions are implemented slightly differently in 64-bit. In particular, the way that exceptions store the catchable type is changed. There is a built-in that lets you determine if the exception is of a given type with MSVC 2005 and later which can be used with 64-bit builds, however: _is_exception_typeof(). It's a bit less thorough than walking the _CatchableType array, but as long as you don't use multiple inheritance with your exception types, it'll be a good enough solution for most cases. One of these days I might reverse engineer the exception mechanism for 64-bit and update the article.

Also, the code for doing the stack walk is 32-bit x86 specific. Take a look at where the stack frame is first constructed. The members get filled with EIP, ESP and EBP. For x86-64 you'd want to use RIP and RSP.

Share this post


Link to post
Share on other sites
Ok I got the main bit working. I'm thinking that creating a minidump is likely to be more useful than just a stack trace (don't you need the pdb for all the modules to be present on the end users machine anyway to get one with symbol names anyway?).


What exactly is the situation with stack overflow exceptions? I just intentionally caused one (endless recursion) and found I was good to allocate over 10KB on the stack before it broke (access violation, which having look around I found was to be expected as I hadn't recreated the guard page at the end of the stack).

I found a SetThreadStackGuarantee which appears to guarantee some space for the exception filter for Windows Server 2003 and later, so is there some default amount for all Windows versions?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!