【发布时间】:2013-02-26 10:48:41
【问题描述】:
我正在用 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
我不明白为什么它的行为不同。请任何人帮忙。
【问题讨论】:
-
显示 GetValue() 方法的内容
-
向我们展示
Test的定义,并向我们展示调试和发布选项在 SEH 和 C++ 异常方面有何不同,有一些选项可供选择。或者更好的是向我们展示在发布模式下对__try{}块的反汇编。它可能有一些更好的线索。 -
我担心
pTest是一个指向类的指针,它可能不需要为了执行GetValue()而取消引用,并且编译器认识到,当在发布模式下启用优化时.或者甚至它认为GetValue()是无用的,并且不会生成任何代码来调用它。编译器也有可能看到取消引用 NULL 指针会导致未定义的行为,并决定在编译时通过修改代码来惩罚你,它完全有权这样做。gcc因这样做而臭名昭著。 -
谢谢阿列克谢。你说的对。由于空指针检查的编译器优化,它实际上并没有引发 exception_access_violation。当我使用 RaiseException() 显式抛出异常时,它开始在调试\发布模式下显示类似的行为。但是 EXCEPTION_EXECUTE_HANDLER 并没有完全按照文档所说的那样做。根据文档,它应该首先在 __except() 之后执行块 {},然后在发生异常时继续执行。
-
您要么误解了文档,要么做错了什么。 SEH 工作正常。我将上述评论移到我的答案中,因为这是实际的调试与发布问题。