Exit()和 abort()之间的区别是什么?

在 C 和 C + + 中,exit()abort()的区别是什么?我试图结束我的程序后一个错误(不是一个例外)。

78261 次浏览

Abort 发送 SIGABRT 信号,出口只是关闭应用程序执行正常的清理。

您可以随心所欲地处理 中止行动信号,但默认行为是使用错误代码关闭应用程序。

Abort 不会对静态和全局成员执行对象销毁,但是 出口会。

当然,当应用程序完全关闭时,操作系统将释放任何未释放的内存和其他资源。

中止行动出口程序终止时(假设您没有覆盖默认行为) ,返回代码将返回到启动应用程序的父进程。

请看下面的例子:

SomeClassType someobject;


void myProgramIsTerminating1(void)
{
cout<<"exit function 1"<<endl;
}


void myProgramIsTerminating2(void)
{
cout<<"exit function 2"<<endl;
}


int main(int argc, char**argv)
{
atexit (myProgramIsTerminating1);
atexit (myProgramIsTerminating2);
//abort();
return 0;
}

评论:

  • 如果取消注释 中止行动: 不打印任何内容,并且不调用某个对象的析构函数。

  • 如果像上面这样注释 中止行动: 某个对象析构函数将被调用,您将得到以下输出:

退出函数2
退出函数1

abort() 退出程序时,不会首先调用使用 atexit()注册的函数,也不会首先调用对象的析构函数。exit()在退出程序之前同时执行这两个操作。但是它不为自动对象调用析构函数。那么

A a;
void test() {
static A b;
A c;
exit(0);
}

将正确破坏 ab,但不会调用 c的破坏函数。abort()不会调用这两个对象的析构函数。由于这是不幸的,C + + 标准描述了一种确保正确终止的替代机制:

具有自动存储持续时间的对象都在一个程序中销毁,该程序的函数 main()不包含自动对象,并执行对 exit()的调用。控件可以通过引发在 main()中捕获的异常直接转移到这样的 main()

struct exit_exception {
int c;
exit_exception(int c):c(c) { }
};


int main() {
try {
// put all code in here
} catch(exit_exception& e) {
exit(e.c);
}
}

不要调用 exit(),而是安排代码 throw exit_exception(exit_code);

abort发送 SIGABRT信号。abort不会返回给调用者。SIGABRT信号的默认处理程序关闭应用程序。刷新 stdio文件流,然后关闭。然而,C + + 类实例的析构函数却不是(这一点不确定——也许结果是未定义的?).

exit有自己的回调函数,用 atexit设置。如果指定了回调(或者只指定了一个) ,那么将以与其注册顺序相反的顺序调用它们(如堆栈) ,然后程序退出。与 abort一样,exit不返回给调用者。刷新 stdio文件流,然后关闭。此外,C + + 类实例的析构函数也被调用。

在 exit ()手册页:

函数导致正常的进程终止,并且 状态 & 0377返回给父母。

在 abort ()手册页中:

Abort ()首先解除 SIGABRT 信号的阻塞,然后引发该信号 调用进程的信号。这将导致进程的异常终止,除非 SIGABRT 信号被捕获并且信号被捕获 处理程序没有返回。

当程序调用 exit()时会发生以下情况:

  • 执行由 atexit函数注册的函数
  • 将刷新和关闭所有打开的流,删除由 tmpfile创建的文件
  • 程序以指定的主机退出代码终止

abort()函数向当前进程发送 SIGABRT信号,如果没有被捕获,程序将终止,并且不保证打开的流被刷新/关闭或者通过 tmpfile创建的临时文件被删除,不调用 atexit注册的函数,并且返回一个非零的退出状态给主机。