中止,终止或退出?

The*_* do 103 c++

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

Tyl*_*nry 139

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

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

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

在C++中,您通常希望避免调用abortexit出错,因为您最好抛出异常并让调用堆栈中的代码进一步决定是否结束该程序.你是否exit用于成功是一个环境问题 - 是否有必要在除了返回声明之外的某个地方结束程序main.

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

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

  • 你能用C++ 11信息更新这个答案吗?现在似乎有了在catch(...)和终止处理程序中获取异常的方法. (9认同)
  • @seattlecpp 你可以重新抛出它并捕获对它的引用,然后你可以检查它 (3认同)
  • 在 C++ 中,终止处理程序 *确实* 可以通过 `std::current_exception()` 访问异常。请参阅此处的示例:https://akrzemi1.wordpress.com/2011/10/05/using-stdterminate/ (2认同)

And*_*zej 14

std :: abort和std :: exit(以及更多:std :: _ Exit,std :: quick_exit)只是较低级别的函数.您可以使用它们告诉程序您希望它完全执行的操作:要调用的析构函数(以及是否),要调用的其他清理函数,要返回的值等等.

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

特别要注意的是,std :: terminate被认为是上下文中的异常处理程序,其中由于无法处理的抛出异常而调用了std :: terminate,您可以检查异常是什么并使用C++检查它11使用std :: rethrow_exception和std :: current_exception.这一切都在我的帖子中.


Ser*_*tch 10

quick_exit()!

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

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

注意:直到2015版本,MSVC++支持quick_exit().


Dan*_*iel 6

  • 当发生无法处理的异常时,会自动调用 terminate()。默认情况下,terminate() 调用 abort()。您可以使用 set_terminate() 函数设置自定义句柄。

    abort() 发送 SIGABRT 信号。

    exit() 不一定是坏事。它成功退出应用程序,并以 LIFO 顺序调用 atexit() 函数。我通常不会在 C++ 应用程序中看到它,但是,我确实在许多基于 Unix 的应用程序中看到它,它在最后发送退出代码。通常 exit(0) 表示应用程序成功运行。

  • 不成功!在 Unix 和 DOS 中,exit(0) 表示成功,任何其他传递给 exit() 的值表示失败,而不是相反! (8认同)

APr*_*mer 5

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


小智 5

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

int main() {
    try {
       // your stuff
    }
    catch( ... ) {
       return 1;    // or whatever
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为了确保堆栈展开,你应该总是在main中捕获.但我会从捕获中重新抛出.如果您已在调试中编译,某些操作系统可以自动调用调试基础结构. (13认同)
  • -1因为这不能回答问题的一半."[中止,终止或退出之间有什么区别?]"这是一个更好的答案:http://stackoverflow.com/a/397081/353094另外http://stackoverflow.com/a/2820407/353094也很棒回答. (8认同)
  • @Neil:基本同意,但应该报告和重新播放程序无法处理的异常.让应用崩溃. (6认同)
  • @John我之所以感到惊讶的原因是,虽然根据实际实现异常的方式它是完全合理的,但它打破了异常"向上传播"直到找到合适的处理程序(或终止是所谓的).泄漏的抽象虽然经常是不可避免的,但遇到时一定会令人惊讶. (6认同)
  • 即使是顶级处理程序也未捕获的异常可能会调用转储进程并上载异常报告的系统报告工具,以供开发人员注意,例如Windows错误报告,Mac OS X错误报告和iPhone应用程序错误日志. (5认同)
  • 投票结果是因为如果你正在堕胎,你不想放松,因为这个过程可能已经干了. (5认同)
  • 这不是一个好的答案.虽然也应该解决例外问题,但要告诉一些人忽视他们询问的其他3件事是错误的.特别是,当作者明确表示这是一个例外,他们无法妥善处理.在这种情况下,例外不是答案. (2认同)
  • 我也投票了。尽管该解决方案可能是有效且不错的解决方案,但它并未解决大部分问题,即这三者之间的差异。 (2认同)