2

我正在用 SEH 做一些实验。在我的代码中,我在 __try 子句中编写了导致错误的块,并在 __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;

__except() 的第二个参数是以下之一 -

EXCEPTION_CONTINUE_SEARCH 无法识别异常。继续在堆栈中搜索处理程序,首先是包含 try-except 语句,然后是具有下一个最高优先级的处理程序。

EXCEPTION_CONTINUE_EXECUTION 异常被识别但被解除。在发生异常的地方继续执行。

EXCEPTION_EXECUTE_HANDLER 识别出异常。通过执行 __except 复合语句将控制权转移到异常处理程序,然后在发生异常的点继续执行。

当我使用 EXCEPTION_CONTINUE_EXECUTION/EXCEPTION_EXECUTE_HANDLER 时,它不会在异常发生点继续执行(可能是我误解了异常发生点的含义)。当我在调试模式下运行它时,输出是

caught
Exception handled

当我在发布模式下运行它时,输出是

continue after exception
Exception handled

我不明白为什么它的行为不同。任何人请帮忙。

4

2 回答 2

4

@Joachim 正确指出了逗号运算符问题。

我认为,__except()应该是这样的:

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

如果异常是访问冲突,这将使异常处理程序执行。如果不是,则异常将传播到最近的 external __try(如果有)。

我担心这pTest是一个指向类的指针,它可能不需要为了执行而取消引用,GetValue()并且编译器会识别出在发布模式下启用优化时。或者甚至它认为GetValue()是无用的并且不会生成任何代码来调用它。编译器也有可能看到取消引用 NULL 指针会导致未定义的行为,并决定在编译时通过修改代码来惩罚你,它完全有权这样做。例如,gcc 因这样做而臭名昭著。

于 2013-02-26T11:10:47.260 回答
1

表达方式

GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION,EXCEPTION_EXECUTE_HANDLER

不符合您的预期。它所做的是比较GetExceptionCode()withEXCEPTION_ACCESS_VIOLATION的结果,但整个表达式的结果是EXCEPTION_EXECUTE_HANDLER

在 Wikipedia 上阅读有关逗号运算符的更多信息。

您想要做的是,可能是:

GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || GetExceptionCode() == EXCEPTION_EXECUTE_HANDLER
于 2013-02-26T11:03:09.637 回答