Question

I was doing some experiments with SEH. In my code I wrote the error causing block in __try clause and a handler in __except().

__try{
Test *pTest = 0;
int k = pTest->GetValue();
cout << "continue after exception" << endl;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION,EXCEPTION_EXECUTE_HANDLER)
{
 cout << "caught!!" << endl;
}
cout << "Exception handled" << endl;

The second parameter to __except() is either of these -

EXCEPTION_CONTINUE_SEARCH Exception is not recognized. Continue to search up the stack for a handler, first for containing try-except statements, then for handlers with the next highest precedence.

EXCEPTION_CONTINUE_EXECUTION Exception is recognized but dismissed. Continue execution at the point where the exception occurred.

EXCEPTION_EXECUTE_HANDLER Exception is recognized. Transfer control to the exception handler by executing the __except compound statement, then continue execution at the point the exception occurred.

When I use EXCEPTION_CONTINUE_EXECUTION/EXCEPTION_EXECUTE_HANDLER it does not continue execution at the point of exception occurrence (may be I am misinterpreting the meaning of point of exception occurrence). When I run it in debug mode, the output is

caught
Exception handled

When I run it in release mode, the output is

continue after exception
Exception handled

I could not understand why it is behaving differently. Anyone please help.

Was it helpful?

Solution

@Joachim points out correctly about the comma operator problem.

I think, the __except() should look like this:

__except((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ?
         EXCEPTION_EXECUTE_HANDLER :
         EXCEPTION_CONTINUE_SEARCH)

This will make the exception handler execute if the exception is an access violation. If it's not, the exception will propagate up to the closest outer __try, if any.

I'm fearing that pTest is a pointer to a class and it may not need to be dereferenced in order to execute GetValue() and the compiler recognizes that when optimizations are enabled in the release mode. Or maybe even it sees GetValue() as useless and does not generate any code to call it. It's also possible that the compiler sees that dereferencing a NULL pointer results in undefined behavior and decides to punish your for it at compile time by screwing with your code, it has every right to do it. gcc is notorious for doing it, for example.

OTHER TIPS

The expression

GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION,EXCEPTION_EXECUTE_HANDLER

doesn't do what you expect it to. What it does is compare the result of GetExceptionCode() with EXCEPTION_ACCESS_VIOLATION, but the result of the whole expression is EXCEPTION_EXECUTE_HANDLER.

Read more about the comma operator at Wikipedia.

What you want to do is, probably:

GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || GetExceptionCode() == EXCEPTION_EXECUTE_HANDLER
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top