是否存在使用catch all子句的情况:catch(...)是否合理?

Alo*_*lon 5 c++ exception-handling

每次我看到抓住所有声明:

try 
{
  // some code 
}
catch (...)
{

}
Run Code Online (Sandbox Code Playgroud)

一直是一种虐待.

反对使用缓存所有子句的论据是显而易见的.它会抓住 任何东西,包括操作系统产生的异常,如访问冲突.由于异常处理程序无法知道它正在处理什么,因此在大多数情况下,异常将表现为模糊的日志消息或一些不连贯的消息框.

所以catch(...)看起来本身就是邪恶的.

但它仍然用C++实现,其他语言(Java,C#)实现了类似的机制.那么有些情况下它的使用是否合理?

MSa*_*ers 6

(1)声明不会捕获操作系统异常.您对"访问冲突"一词的使用背叛了Windows背景; 旧的MSVC++版本确实如此.

(2)无论如何,catch-all行为对于具有特定目的的线程非常有用.捕获失败允许线程报告失败.没有它,程序的其他部分需要处理线程消失的可能性.它还允许您记录哪个线程失败,以及用于启动线程的参数.


Pav*_*aev 5

一般来说,它是合理的情况是你记录异常(或做类似的事情)或做一些清理,然后立即重新抛出.

特别是在C++中,登录catch(...)块是非常没有意义的,因为你没有任何方法可以获得异常,并且清理是没有意义的,因为你应该使用RAII.在析构函数中使用它似乎是唯一合法的案例.


DrP*_*zza 4

反对使用cache all 子句的论点是显而易见的,它会捕获任何内容,包括操作系统生成的异常,例如访问冲突。由于异常处理程序无法知道它正在处理什么,因此在大多数情况下,异常将表现为模糊的日志消息或一些不连贯的消息框。

如果没有捕获这些相同的异常,您会得到...一个不连贯的消息框。

catch(...) 至少可以让我呈现我自己的消息框(并调用自定义日志记录、保存故障转储)。

我认为 catch(...) 在析构函数中也有合理的用途。析构函数不能抛出——好吧,我的意思是,它们可以抛出,但是如果析构函数在堆栈展开期间由于正在进行的异常而抛出,则程序将终止,因此它们不应该允许异常逃逸。一般来说,允许第一个异常继续展开比终止程序更好。

另一种情况是在可以运行任意函数的工作线程中;通常,如果任务抛出异常,您不希望发生意外崩溃。工作线程中的 catch(...) 提供了半有序清理和关闭的机会。

  • 该消息将是“拨打 911”:) (2认同)