菜鸟笔记
提升您的技术认知

exit

exit与return

exit(exiitCode):这个表示整个程序终止执行,也就是说在整个程序中,只要调用 exit ,就结束,并且可以返回一个数值给调用这个程序的环境,环境就可以知道这个程序执行的结果。exit为C++的退出函数,声明于stdlib.h中,对于C++其标准的头文件为cstdlib。

return:一般是函数返回的结果,这个结果可以是int类型、short类型、bool类型等所有c++已有的类型和用户自定义的类型,甚至可以规定不返回任何值,直接是void,这个值是返回给调用这个函数的环境。return() 是当前函数返回,当然如果是在主函数main,自然也就结束当前进程了,如果不是,那就是退回上一层调用。在多个进程时,如果有时要检测上进程是否正常退出的,就要用到上个进程的返回值。

也就是说:

exit 这个是返回给调用该"程序"的外界环境

return 这个是返回给调用该"函数"的外界环境

int Fun()
{
    exit(3);  // 函数执行到这里的时候就终止程序并且返回3
    return 2; // 如果不添加这句话的话会编译出错,因为Fun()函数要求返回int型变量
              // 上一行exit(3)并不是"函数的"返回值
}
int main()
{
   int i = Fun(); // Fun()函数还没有执行完就退出程序了,所以i不会被赋予任何值
   return 0;  // 程序根本就不会执行到这里来
}

exit和return在main中的作用基本相同:return x 和 exit(x) 基本是一个意思。

【补充】exit()就是退出,传入的参数是程序退出时的状态码,0表示正常退出,其他表示非正常退出,一般都用-1,标准C里有EXIT_SUCCESS和EXIT_FAILURE两个宏,用exit(EXIT_SUCCESS)可读性比较好一点,这两个宏定义在stdio.h里。。此外,使用exit()时,可以不论main()的返回值类型。

 

两个问题

问题1:exit的返回值是给谁用的?

每个运行着的程序都是进程,而进程就会有父进程,父进程通常是直接启动你的进程,父进程死亡的进程会被 init 收养,其父进程变为 init,而 init 的父进程是进程 0,进程 0 则是系统启动时启动的第一个进程。exit() 里面的参数,是传递给其父进程的。对父进程来说,你的进程仿佛是一个函数,而函数可以有返回值。所以exit() 的参数是给自己的父进程使用的。通常一个程序的父进程可能是任何进程,因此我们无法预期我们的父进程是否规定必须要有这个返回值,那么我们应当提供这个返回值,以保证不同的父进程的需求得到满足。

问题2:为什么要使用 exit() 函数?

历史原因,虽然现在大多数平台下,直接在 main() 函数里面 return 可以退出程序。但是在某些平台下,在 main() 函数里面 return 会导致程序永远不退出(因为代码已经执行完毕,程序却还没有收到要退出的指令)。换句话说,为了兼容性考虑,在特定的平台下,程序最后一行必须使用 exit() 才能正常退出,这是 exit() 存在的重要价值。

 

进程终止

C程序的终止分为两种:正常终止和异常终止

【正常终止分为】return、exit、_exit、_Exit、pthreade_exit

【异常终止分为】abort、SIGNAL、线程响应取消

主要说一下正常终止的前4种,即exit系列函数:

#i nclude <stdlib.h> /* ISO C */
void exit(int status);
void _Exit(int status);
#i nclude <unistd.h> /* POSIX */
void _exit(int status);

以上3个函数的区别是:

exit()(或return 0)会调用终止处理程序和用户空间的标准I/O清理程序(如fclose),_exit和_Exit不调用而直接由内核接管进行清
理,因此,在main函数中exit(0)等价于return 0。

 

如何看到exit的值?

如果你的进程为nginx,则执行./nginx后再执行echo $? ,就可以看到你的进程的返回值,也就是exit(x)的x!