SEH: corrupt program state when catching access violation

Started by
6 comments, last by Adam_42 9 years, 5 months ago

During development I've opted to using Windows SEH. As I'm still working on parts of the base code and haven't quite figured everything out yet, there are cases where I need to debug hardware exceptions that occur due to code changes that affect completely different parts of the program. This is further complicated by the fact that I'm running a heavily multithreaded environment with job stealing and issues can easily propagate across threads.

My current exception handling scheme is pretty straightforward: at root level each thread provides its own __try/__except block, which is the only handler for that particular thread. I guard most heavier functions I'm working on so I have access to a rough flow graph of my own, including a runtime stack trace of any guarded functions. The function guards track program flow per-thread, which means this information should be available when an exception is caught by that particular thread's handler. That is, it is available - at least when I throw an exception myself.

When a hardware exception occurs, however, the entire program state becomes corrupt. The __except handler is properly called, but two things happen:

1) the state that stores my own stack trace becomes invalid. When I step into the handler, the structure that holds the program state seems to have a moved to a base address of 0xFEFEFEFE. I'm not sure why this happens.

2) more importantly, when setting a breakpoint in the handler, the debugger provides no stack trace extending back further than the function in which the handler resides. This means that despite the extensive information that should be available to me, I can't even gen an estimate as to where the problem occurred either from the debugger's stack trace or my own

Why is this and/or what am I missing and/or doing wrong?

In short, what I want is a reliable way of localizing hardware exceptions - if the debugger won't show me where, I'd like to at least be able to access my program state inside the exception handler so I can get a rough idea.

Advertisement
32-bit or 64-bit?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

32-bit build on a 64-bit hardware and OS. Windows 8.1.

SEH on 32-bit programs does not respect C++ stack unwinding semantics. It is highly inadvisable to try and mix C++ object lifetime management with SEH stack unwinding. SEH stack unwinds may appear to corrupt call stacks, will screw with your RAII code, and will probably generally make things worse instead of better.

If you genuinely need SEH to snag hardware traps, you need to put the __try/__except block as close to the faulting location as possible, i.e. the exact opposite of the way you're doing it.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

SEH on 32-bit programs does not respect C++ stack unwinding semantics. It is highly inadvisable to try and mix C++ object lifetime management with SEH stack unwinding. SEH stack unwinds may appear to corrupt call stacks, will screw with your RAII code, and will probably generally make things worse instead of better.

If you genuinely need SEH to snag hardware traps, you need to put the __try/__except block as close to the faulting location as possible, i.e. the exact opposite of the way you're doing it.

Hm - can you elaborate on what I should take away from this:

1) would compiling to 64 bits alleviate or resolve the issue?

2) is there an alternative to SEH to trap hardware faults? (as far as I know there isn't on Windows)

3) since I don't know where to set up my handler when trying to locate the source of the fault in the first place, SEH is pretty much useless and I should just be prepared to do what I've been doing so far - manually step though code until I can reason where the fault can originate from

Why don't you just run under the debugger and have it break when the exception is thrown?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Well... That took less than 20 seconds. I can't believe my exception breaks simply weren't properly set up in the IDE. Now I feel really stupid...

There's also SetUnhandledExceptionFilter() if you need to catch them at runtime.

You may also find MiniDumpWriteDump() handy.

This topic is closed to new replies.

Advertisement