中止,终止或退出?

时间:2010-05-12 15:28:34

标签: c++

这三者之间有什么区别,如果我无法正常处理异常,我该如何结束程序呢?

6 个答案:

答案 0 :(得分:132)

  • abort 表示程序的“异常”结束,并引发POSIX信号SIGABRT,这意味着将调用您为该信号注册的任何处理程序,尽管该程序在任何一种情况下,仍然会在双语后终止通常,您将在C程序中使用abort来退出意外错误情况,其中错误可能是程序中的错误,而不是输入错误或网络故障。例如,如果发现数据结构中有一个NULL指针,那么你可能会abort,这在逻辑上永远不会发生。

  • 退出表示程序的“正常”结束,但这可能仍然表示失败(但不是错误)。换句话说,如果用户提供了无法解析的输入,或者无法读取文件,则可能exit带有错误代码。退出代码为0表示成功。 exit还可以选择在程序结束之前调用处理程序。这些是在atexiton_exit函数中注册的。

  • std :: terminate 是存在未处理异常时在C ++程序中自动调用的内容。这基本上是与abort等效的C ++,假设您通过抛出异常来报告所有异常错误。这会调用由std::set_terminate函数设置的处理程序,默认情况下只调用abort

在C ++中,您通常希望避免在出错时调用abortexit,因为您最好抛出异常并让调用堆栈中的代码进一步决定是否结束程序是合适的。你是否使用exit来取得成功是一个环境问题 - 除了main中的return语句之外的某个地方结束程序是否有意义。

std::terminate应被视为最后一个错误报告工具,即使在C ++中也是如此。 std::terminate的问题是终止处理程序可以访问未处理的异常,因此无法分辨它是什么。在try { } catch (std::exception& ex) { }块中包装整个main通常要好得多。至少那时您可以报告有关从std::exception派生的异常的更多信息(尽管当然,不是从std::exception派生的异常仍然会以未处理的方式结束)。

main中包装try { } catch(...) { }的正文并不比设置终止处理程序好多了,因为再次无法访问相关的异常。 编辑:根据Neil Butterworth的回答,有一个好处是在这种情况下堆栈是解开的,对于未处理的异常(有点令人惊讶地)是不正确的。

答案 1 :(得分:14)

std :: abort和std :: exit(以及更多:std :: _ Exit,std :: quick_exit)只是较低级别的函数。你用它们来告诉程序你想要它做什么:destructors(和if)调用什么,调用什么其他清理函数,返回什么值等等。

std :: terminate是一个更高级别的抽象:它被调用(通过运行时或你)来指示程序中发生了错误,并且由于某种原因,它无法通过抛出异常来处理。这种情况的必要性通常发生在异常机制本身发生错误时,但是当您不希望程序继续超出给定错误时,您可以随时使用它。当std :: terminate被调用in my post时,我编译了完整的情况列表。没有指定std :: terminate的作用,因为你可以控制它。您可以通过注册任何功能来配置行为。您遇到的限制是函数无法返回到错误站点,并且无法通过异常退出,但从技术上讲,您甚至可以在内部启动消息泵。有关您可以在其中执行的有用事项的列表,请参阅my other post

特别要注意,std :: terminate在上下文中被视为异常处理程序,其中由于无法处理的抛出异常而调用std :: terminate,您可以检查异常是什么并使用它来检查它C ++ 11使用std :: rethrow_exception和std :: current_exception。全部都在my post

答案 2 :(得分:9)

quick_exit()

如果您的程序是多线程的,那么调用exit()很可能会导致崩溃,因为将尝试在不退出其线程的情况下销毁全局/静态std::thread对象。

如果要返回错误代码并正常退出程序(或多或少),请在多线程程序中调用quick_exit()。 对于异常终止(无法指定错误代码),可以调用abort()std::terminate()

注意:quick_exit() has not been supported by MSVC++直到2015年版。

答案 3 :(得分:6)

我的建议是不要使用它们中的任何一个。相反,捕获你在main()中无法处理的异常,然后从那里返回。这意味着您可以保证堆栈展开正确并且所有析构函数都被调用。换句话说:

int main() {
    try {
       // your stuff
    }
    catch( ... ) {
       return 1;    // or whatever
    }
}

答案 4 :(得分:4)

  • 自动调用terminate() 当发生异常时,不能 被处理。默认情况下,terminate() 调用abort()。您可以设置自定义 使用set_terminate()函数处理。

    abort()发送SIGABRT信号。

    exit()不一定是坏事 事情。它成功地退出了 应用程序,并调用atexit() LIFO订单中的功能。我不 通常在C ++中看到这一点 但是,我确实看到了它 许多基于unix的应用程序 最后发送一个退出代码。 通常,出口(0)表示a 成功运行该应用程序。

答案 5 :(得分:2)

  • 终止使您可以注册调用时会发生什么。应该是另外两个中的一个。
  • exit是正常退出,允许指定退出状态。由at_exit()注册的处理程序运行
  • abort是异常退出。唯一运行的是SIGABRT的信号处理程序。