c++ 放弃、终止还是退出?

lqfhib0f  于 2022-12-01  发布在  其他
关注(0)|答案(6)|浏览(192)

这三种方法有什么区别?如果出现无法正确处理的异常,如何结束程序?

xu3bshqb

xu3bshqb1#

*abort表示程序“异常”结束,并引发POSIX信号SIGABRT,这意味着您为该信号注册的任何处理程序都将被调用,尽管在这两种情况下程序仍然会终止。通常您会在C程序中使用abort来退出意外错误情况,这种错误可能是程序中的bug。而不是错误的输入或网络故障。例如,如果发现一个数据结构中有一个NULL指针,而在逻辑上不应该发生这种情况,则可以使用abort
*exit表示程序“正常”结束,尽管这可能仍表示失败换句话说,如果用户提供了无法解析的输入,您可能会得到exit错误代码,或无法读取文件。退出代码0表示成功。exit在结束程序之前还可以选择调用处理程序。这些寄存器使用atexiton_exit函数注册。
*std::terminate是C程序中出现未处理异常时自动调用的函数。这基本上是Cabort的等价函数,假设您通过抛出异常来报告所有异常错误。这将调用由std::set_terminate函数设置的处理函数,默认情况下,std::set_terminate函数只调用abort

在C中,您通常希望避免在出错时调用abortexit,因为您最好抛出一个异常,让调用堆栈中更上层的代码来决定是否结束程序。无论在main中的return语句之外的某个地方结束程序是否有意义。
std::terminate应该被看作是最后的错误报告工具,即使在C
中也是如此。std::terminate的问题是终止处理程序 * 不 * 能够访问未处理的异常,因此无法判断它是什么。通常最好将整个main封装在一个try { } catch (std::exception& ex) { }块中。至少这样,您可以报告更多关于从std::exception派生的异常的信息(当然,不是从std::exception派生的异常仍然会以未处理结束)。
main的主体 Package 在try { } catch(...) { }中并不比设置一个终止处理程序好多少,因为你同样无法访问所讨论的异常。当一个异常完全未被捕获时,堆栈展开是否完成是由实现定义的,所以如果你需要有保证的堆栈展开,这将是一种获得它的方法。

unguejic

unguejic2#

std::中止和std::退出(以及更多:std::_Exit、std::quick_exit)只是较低级别的函数。你用它们来告诉程序你想让它做什么:调用什么析构函数(和if)、调用什么其他清除函数、返回什么值等。
std::terminate是更高级别的抽象:它被调用(由运行时或您自己调用)来指示程序中出现了错误,并且由于某种原因,无法通过抛出异常来处理。通常,当异常机制本身出现错误时,需要这样做,但是当您不希望程序在给定错误后继续运行时,可以随时使用它。我编译了调用in my post时std::terminate的完整情况列表。没有指定std::terminate做什么,因为您可以控制它。您可以通过注册任何函数来配置行为。您的限制是函数不能返回到错误站点,也不能通过异常退出,但从技术上讲,您甚至可以在内部启动消息泵。要了解您可以在内部做的有用事情的列表,请参阅my other post
特别要注意的是,当std::terminate被调用时,它会被视为一个异常处理程序,因为抛出了一个无法处理的异常,你可以检查这个异常是什么,并使用C++11中的std::rethrow_exception和std::current_exception来检查它。

amrnrhlw

amrnrhlw3#

我的天!
如果你的程序是多线程的,那么调用exit()很可能会导致崩溃,因为全局/静态std::thread对象将在不退出它们的线程的情况下试图析构。
如果你想返回一个错误代码并正常地退出程序(或多或少),在多线程程序中调用quick_exit()。对于异常终止(不可能指定错误代码),可以调用abort()std::terminate()
注:quick_exit() has not been supported by MSVC++至2015版。

pkln4tw6

pkln4tw64#

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

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

62lalag4

62lalag45#

  • terminate让你有可能登记当它被调用时会发生什么。应该是另外两个之一。
  • exit是一个正常的退出,允许指定退出状态。由at_exit()注册的处理程序运行
  • abort是一个异常退出。2唯一运行的是SIGABRT的信号处理程序。
gv8xihay

gv8xihay6#

我的建议是不要使用它们中的任何一个。相反,catch表示你不能在main()中处理的异常,并简单地从return开始。这意味着你可以保证堆栈展开正确发生,并且所有析构函数都被调用。换句话说:

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

相关问题