C++/GCC:如何在编译时检测未处理的异常

C++/GCC: How to detect unhandled exceptions in compile time

本文关键字:检测 未处理 异常 编译 GCC C++      更新时间:2023-10-16

简介:在Java中,如果您没有捕捉到异常,您的代码甚至不会编译,编译器会在未处理的异常上崩溃。

问题:在这种情况下,有没有办法告诉GCC像Java一样"严格",并在未处理的异常上引发错误或至少发出警告?

如果没有,是否有IDE(请使用Unix)可以突出显示此类情况作为警告?

这在C++中是不可能的。异常规范是函数声明的一部分,但不是其类型的一部分。任何间接调用(通过指针或虚拟调用)都会完全清除有关异常的任何信息。

无论如何,C++11中的异常规范都被弃用,取而代之的是noexcept,因此任何编译器都不太可能费力地增强这种语言功能。

对C++函数的唯一保证是它永远不会抛出异常:

void f() noexcept;

但是,当抛出异常时,这将在运行时终止程序。它在编译时没有经过验证。

如果您想确保错误得到处理,最接近的方法是返回一个类型的值,该值用一个成员函数封装boost::variant<OK, Error>,该成员函数接受两个回调:一个回调用于OK情况,一个回调适用于Error情况。

您可以始终使用:

int main()
{
   try {
      ... your usual main ... 
   }
   catch(...)
   {
       std::cerr << "Unhandled exception caught" << std::endl;
   }
}

然而,这是一个相当糟糕的解决方案。

不幸的是,C++的本质使得它很难捕捉到某些东西抛出异常而没有得到处理的情况,因为几乎所有东西都有可能抛出异常。我只能想到代码审查——也许代码分析工具,比如围绕CLANG构建的工具,能够做到这一点,但它可能不会100%准确。事实上,我甚至不确定Clang Analyzer目前是否完全理解投掷/尝试/接球,因为它似乎没有捕捉到一些相当基本的错误http://clang-analyzer.llvm.org/potential_checkers.html(见"例外情况"标题)。

首先,您关于Java的声明是false;只能确定异常类型会阻止代码编译。以及大多数情况下,这些类型的异常与事物相对应通过返回代码可以更好地处理。例外情况通常只有在传播错误时才是合适的解决方案大量的函数,并且您不想添加所有这些函数的异常规范。

这就是Java与众不同的真正原因:从java.lang.Error派生通常应该是崩溃(C++中的断言失败等);以及例外情况从java.lang.RuntimeException派生应该是中的例外C++两者都没有在Java中检查,因为它没有让每个函数声明它可能抛出其中之一。

至于其余部分,您要捕获的异常在调用代码中,它们通常是最好的处理方式通过返回代码而不是异常;Java可能会使用异常因为它没有out参数,所以可以使用返回代码更加尴尬。当然,在C++中,您也可以静默地忽略返回代码,这是一个缺点(但是历史原因等)。但真正的问题是合同,这比函数f可能抛出/返回x要复杂得多;它更像是"函数f抛出/返回x,如果满足条件c"。我所知道的任何语言一种强制执行的手段。在C++中(对于已检查的异常在Java中),异常规范更多地遵循"函数f只抛出x"。一般来说不是很有用,除非"x"表示所有异常。为了编写真正健壮的代码,您需要一些函数保证永远不会扔。有趣的是,你可以在C++中指定此项,包括C++11之前(throw())和之后(noexcept);在Java中不能,因为不能指定函数不会抛出CCD_ 9。

(或者java.lang.Error,但这不是什么问题,因为如果你得到了其中一个,你的应用程序无论如何都被冲洗掉了。只是你预计如何康复java.lang.VirtualMachineError?当然,你不能确实希望能够在C++。虽然java.lang.OutOfMemoryError派生来自CCD_ 13;虽然不容易,也不容易总是适用的,我已经成功地编写了C++代码从std::bad_alloc中回收。)