Java 我可以把try/catch放在崩溃的OS API周围吗?

Java 我可以把try/catch放在崩溃的OS API周围吗?,java,c++,winapi,try-catch,access-violation,Java,C++,Winapi,Try Catch,Access Violation,我使用Windows操作系统库来处理图像文件。有时,它会毫无理由地在内部崩溃,所有的输入都是合理的,这不是线程问题。故障是内存A/V 那么,这类事情的不利方面是什么: try { pFoo = OsAPIThatCrashes(); } catch { pFoo = NULL; } 这行得通吗?我们不会在代码中的任何其他地方使用异常。这样做可能没有任何好处——只有当操作系统API抛出一个您可以捕获的异常时,它才会有帮助。如果它正在这样做,而您没有捕获到异常,那么您通常会从应用程序中获得

我使用Windows操作系统库来处理图像文件。有时,它会毫无理由地在内部崩溃,所有的输入都是合理的,这不是线程问题。故障是内存A/V

那么,这类事情的不利方面是什么:

try {
  pFoo = OsAPIThatCrashes();
} catch {
  pFoo = NULL;
}

这行得通吗?我们不会在代码中的任何其他地方使用异常。

这样做可能没有任何好处——只有当操作系统API抛出一个您可以捕获的异常时,它才会有帮助。如果它正在这样做,而您没有捕获到异常,那么您通常会从应用程序中获得一个退出,并显示一条错误消息,大意是它通过抛出一个未捕获的异常而退出。除非您看到的是一般顺序上的某些内容,否则在try块中包装调用将不会有任何好处


根据操作系统的不同,您可能可以使用本机异常处理机制来完成更多的工作——例如,在Windows下,您可以使用结构化异常处理来捕获页面错误之类的内容。同样,这是否会有任何好处还不完全清楚——如果一个未处理的异常是问题的根源,它可能会有所帮助,但是如果代码有一个bug,其中(例如)值X==10和值Y==20导致无限循环,或者类似的顺序,那么当代码崩溃时,您可能不得不确定,当Win32 API是一个C库而不使用异常时,MSVC可以实现某些事情,如不需要这样做的异常(如除法零)(由C++标准)。所以:这要视情况而定


最好的办法是找出问题的原因并加以解决。

此时库的内部状态可能不好,因此继续使用它是有风险的。最好修复、崩溃或使用其他库。有时生活很糟糕。

您可能喜欢探索结构化异常处理。结构化异常处理和终止处理机制是Windows操作系统的组成部分

首先,虽然我们都喜欢抨击微软软件的缺陷,但在100个案例中,99个案例的问题不是操作系统、编译器或标准库中的缺陷,而是调用它的代码中的缺陷。无论您使用的是什么WinAPI,它的测试都比大多数(如果不是全部)使用它的代码要彻底得多

进一步,<代码>尝试/<代码> catch < /C> >捕获C++异常,而不是OS异常。(早期版本的VC做得不对,但后来的版本有正确的默认设置。)所以

try
/
catch
不会捕获AV。也就是说,VC提供了捕获操作系统异常的方法。我认为它叫做结构化异常处理,以
\uuuu try
/
\uu catch
为中心,但我不确定,因为我从未使用过它。然而:

一旦您的应用程序遇到AV,所有的赌注都将被取消。AV只是未定义行为表现自身的一种方式,一旦调用了未定义行为(或API代码,无论这种可能性有多大),就无法假设应用程序的状态。你不应该继续


总而言之:你应该努力找出你做错了什么。这样做的一个好方法是尝试将问题归结为一小段重现问题的示例代码。在90%的情况下,这将揭示错误。如果哪怕是一小段代码重现了问题,而您仍然不知道问题出在哪里,那么您就有了一个很好的重新编写案例(或者向MS支持部门求助)。IME,在这10%中有9%的人指出了你的错误,只有剩下的1%会显示出你自己没有犯的错误

> Test/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())) {
}

?您在编译器开关中指定的异常模型是什么?这听起来像是一件可怕的事情。除非你做错了什么,否则操作系统API不会崩溃。想想看——成千上万的其他开发人员使用与您相同的功能,并且没有问题。我建议你解决问题的根本原因,而不是解决它。@Pod:我非常同意“不应该崩溃”。除了一些罕见的API被记录为可能导致访问冲突,并且它们声明您对SEH(结构化异常处理)负责。“罕见”是关键字,我希望OP会解释这种情况。