我使用 Windows 操作系统库来操作图像文件。有时它会在没有明显原因的情况下在内部深处崩溃——所有输入都是合理的,而不是线程问题。崩溃是内存 A/V。
那么,这样的事情有什么缺点:
try {
pFoo = OsAPIThatCrashes();
} catch {
pFoo = NULL;
}
这甚至会起作用吗?我们不会在代码的其他任何地方使用异常。
我使用 Windows 操作系统库来操作图像文件。有时它会在没有明显原因的情况下在内部深处崩溃——所有输入都是合理的,而不是线程问题。崩溃是内存 A/V。
那么,这样的事情有什么缺点:
try {
pFoo = OsAPIThatCrashes();
} catch {
pFoo = NULL;
}
这甚至会起作用吗?我们不会在代码的其他任何地方使用异常。
一方面,虽然我们都喜欢抨击 MS 的软件缺陷,但在 100 种情况下,IME 中有 99 种不是操作系统、编译器或标准库中的错误,而是调用它的代码中的错误。无论您使用什么 Win API - 它都经过了比大多数(如果不是全部)使用它的代码更彻底的测试。
此外,try
/catch
捕获 C++ 异常,而不是操作系统异常。(早期版本的 VC 做错了,但后来的版本有正确的默认值。)所以try
/catch
不会捕获 AV。也就是说,VC 提供了捕获操作系统异常的方法。我认为它被称为结构化异常处理并以__try
/为中心__catch
,但我不确定,因为我从未使用过它。然而:
一旦你的应用程序遇到了 AV,所有的赌注都被取消了。AV 只是未定义行为表现自己的一种方式,一旦您(或 API 代码,尽管这不太可能)调用未定义行为,您就无法假设您的应用程序的状态。你不应该继续。
总结一下:你应该试着找出你做错了什么。一个很好的方法是尝试将问题归结为一小段重现问题的示例代码。在 90% 的情况下,这将揭示错误。如果即使是一小段代码也重现了问题,而您仍然不知道问题出在哪里,那么您有一个很好的重现案例可以回来(或提交 MS 支持)。IME,在这 10% 中的 9 个中,其他人指出了您的错误,只有剩下的 1% 会揭示您没有自己制造的错误。
很有可能这不会有任何好处——只有当操作系统 API 抛出一个您可以捕获的异常时它才会有所帮助。如果它正在这样做,并且您没有捕获异常,那么您通常会从应用程序中退出,并显示一条错误消息,表明它已通过抛出未捕获的异常退出。除非您在该一般顺序上看到某些内容,否则将调用包装在 try 块中的可能性很小。
根据操作系统的不同,您可能能够使用本机异常处理机制来完成更多工作——例如,在 Windows 下,您可以使用结构化异常处理来捕获页面错误之类的事情。同样,尚不完全清楚这是否有任何好处 - 如果未处理的异常是问题的根源,它可能会有所帮助,但如果代码有一个错误,其中(例如)值 X==10 和值 Y == 20 会导致无限循环,或按此顺序执行,您可能必须在代码崩溃时确定,并确保永远不会出现。
此时库的内部状态可能很糟糕,因此继续使用它是有风险的。最好修复它、崩溃或使用不同的库。有时候生活就是一团糟。
try/catch 用于 C++ 异常,您需要使用的是
__try {
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
但是所有这些都会吃掉异常,它不会解决问题并且可能会使库(或您的应用程序!)处于不一致的状态。如果异常是浮点异常,那么您很有可能会继续忽略它,但如果它是访问冲突,那么您可能只是在延迟崩溃。
如果您可以将其确定为特定类型的异常,则可以仅捕获并吃掉该类型
long WINAPI filter(EXCEPTION_POINTERS * pex)
{
EXCEPTION_RECORD * per = pex->ExceptionRecord;
DWORD dwCode = per->ExceptionCode;
if (EXCEPTION_DATATYPE_MISALIGNMENT == dwCode)
return EXCEPTION_CONTINUE_SEARCH; // let a handler above us deal with it.
else if (EXCEPTION_FLT_DIVIDE_BY_ZERO == dwCode)
return EXCEPTION_EXECUTE_HANDLER; // Eat this one
return EXCEPTION_CONTINUE_SEARCH; // let all the rest on through...
}
__try {
...
} __except(filter(GetExceptionInformation())) {
}
虽然 win32 API 是一个 C 库并且不使用异常,但 MSVC 可以将某些事情实现为异常(例如除以零),而这些事情不需要以这种方式(由 C++ 标准)完成。所以:这取决于。
最好的办法是找出导致问题的原因并加以解决。
您可能想探索结构化异常处理。结构化异常处理和终止处理机制是 Windows 操作系统的组成部分。MSDN 参考