return和exit的区别_exit和return-程序员宅基地

技术标签: atexit终止处理程序  _exit和_Exit不调用而直接由内核接管进行清理  return和exit的区别  正常终止和异常终止  

 

转自 :http://blog.csdn.net/firefly_2002/article/details/7960595

 

1. exit用于结束正在运行的整个程序,它将参数返回给OS,把控制权交给操作系统;而return 是退出当前函数,返回函数值,把控制权交给调用函数
2. exit是系统调用级别,它表示一个进程的结束;而return 是语言级别的,它表示调用堆栈的返回。
3. main函数结束时,会隐式地调用exit函数,所以一般程序执行到main()结尾时,则结束主进程。exit将删除进程使用的内存空间,同时把错误信息返回给父进程。
4. void exit(int status); 一般status0,表示正常退出,非0表示非正常退出。

1exit函数和return函数的主要区别是:

1exit用于在程序运行的过程中随时结束程序,其参数是返回给OS的。也可以这么讲:exit函数是退出应用程序,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息。

main函数结束时也会隐式地调用exit函数,exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件。

exit是系统调用级别的,它表示了一个进程的结束,它将删除进程使用的内存空间,同时把错误信息返回父进程。通常情况:exit(0)表示程序正常, exit(1)exit(-1)表示程序异常退出,exit(2)表示系统找不到指定的文件。在整个程序中,只要调用exit就结束。

 

2return是语言级别的,它表示了调用堆栈的返回return是返回函数值并退出函数,通常0为正常退出,非0为非正常退出,请注意,如果是在主函数main, 自然也就结束当前进程了(也就是说,在main()里面,你可以用return n,也能够直接用exit(n)来做),如果不是在main函数中,那就是退回上一层调用。在多个进程时,如果有时要检测上个进程是否正常退出,就要用到上个进程的返回值。

 

2、进程环境与进程控制

exit(int n)其实就是直接退出程序,因为默认的标准程序入口为 int main(int argc, char** argv),返回值是int型的。一般在shell下面,运行一个程序,然后使用命令echo $?就能得到该程序的返回值,也就是退出值。

理论上exit可以返回小于256的任何整数,返回的不同数值主要是给调用者作不同处理的。

对于单独的进程exit的返回值是返回给操作系统的,但如果是多进程,则是返回给父进程的。父进程里面调用waitpid()等函数得到子进程退出的状态,以便作不同处理。根据相应的返回值来让调用者作出相应的处理。

总的说来,exit()就是当前进程把其控制权返回给调用该子程序的主程序, 括号里的是返回值,告诉调用程序该程序的运行状态。

 

1)进程的开始:

C程序是从main函数开始执行, 原型如下: int main(int argc, char *argv[]); 通常main的返回值是int, 正确返回0 

2)进程终止: 

C程序的终止分为两种: 正常终止和异常终止。正常终止分为: return, exit, _exit, _Exit, pthreade_exit。异常中指分为: abort, SIGNAL, 线程响应取消。

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

#include <stdlib.h>  

void exit(int status);

void _Exit(int status);

 

#include <unistd.h>  

void _exit(int status);

以上3个函数的区别是: exit()(return 0)会调用终止处理程序和用户空间的标准I/O清理程序(fclose), _exit_Exit不调用而直接由内核接管进行清理。因此, main函数中exit(0)等价于return 0.

 

3atexit终止处理程序:

ISO C规定, 一个进程最多可登记32个终止处理函数, 这些函数由exit按登记相反的顺序自动调用。如果同一函数登记多次, 也会被调用多次。

 

原型如下

#include <stdlib.h>

int atexit(void (*func)(void));

 

其中参数是一个函数指针, 指向终止处理函数, 该函数无参无返回值。atexit函数本身成功调用后返回0

 

以下面的程序为例:

 

#include <stdlib.h> 

static void myexit1()

{

     printf("first exit handler\n");

static void myexit2()

{

     printf("second exit handler\n");

int main()

{

     atexit(my_exit2)

     atexit(my_exit1)

atexit(my_exit1)

     printf("main is done\n");

     return 0;

}

 

运行结果:

$ ./a.out

main is done

first exit handler

first exit handler

second exit handler

    注意上面的结果,可以发现这些函数exit按登记相反的顺序自动调用(myexit1myexit2)。如果同一函数登记多次, 也会被调用多次(如这里的myexit1)。而这些处理函数都是在程序退出的时候利用atexit函数调用了这些处理函数。但是如果用_exit()退出程序,则它不关闭任何文件,不清除任何缓冲器、也不调用任何终止函数!

 

exit函数在头文件stdlib.h

exit0):正常运行程序并退出程序;

exit1):非正常运行导致退出程序;

return():返回函数,若在main主函数中,则会退出函数并返回一值,可以写为return0),或return 0

详细说:

  1. return返回函数值,是关键字;exit是一个函数

  2. return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。
  3. return是函数的退出(返回)exit是进程的退出。

  4. returnC语言提供的,exit是操作系统提供的(或者函数库中给出的)。

  5. return用于结束一个函数的执行,将函数的执行信息传出个其他调用函数使用;exit函数是退出应用程序,删除进程使用的内存空间,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息,这个信息和机器和操作系统有关,一般是 0 为正常退出,非0 为非正常退出。

  6. 非主函数中调用returnexit效果很明显,但是在main函数中调用returnexit的现象就很模糊,多数情况下现象都是一致的。

 下面是几个例子:

1.

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

  

int main(void)

{

  pid_t pid;

  int count=0;

  

  pid=vfork();

  if(pid==0)

  {

    printf("child: count=%d\n",count);

    printf("child: getpid=%d\n",getpid());

    count=1;

    printf("child: count=%d\n",count);

    // return 0;//会出现段错误

    exit(0); //ok

  }

  else

  {

    printf("\nfather: pid=%d\n",pid);

    printf("father: count=%d\n",count);

  }

  return(0);

}

 

运行结果

?

[root@localhost part1_linux]# gcc fork2.c 

[root@localhost part1_linux]# ./a.out 

child: count=0

child: getpid=9911

child: count=1

  

father: pid=9911

father: count=1

运行结果说明:vfrok时父、子进程共享数据段,fork时是进行拷贝。如果,vfork子进程中,使用return返回时,出现段错误,结果如下:

?

[root@localhost part1_linux]# gcc fork2.c 

[root@localhost part1_linux]# ./a.out 

child: count=0

child: getpid=10864

child: count=1

  

father: pid=10864

father: count=0

段错误

2. 为什么执行结果子进程打印出来 我的父亲是id:1,与父进程id不同

?

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

  

int main()

{

    int i=0;

    pid_t pid;

    printf("还没创建子进程\n");

    i++;

    pid = fork();

    if(pid==-1)

    {

      printf("fork error!\n");

    }

    else if(pid==0)

    {

      i++;

      printf("我是子进程,id%d\n",getpid());

      printf("我的父亲是id:%d\n",getppid());

      printf("-----i=%d-----\n",i);

    }

    else

    {

      i++;

      printf("我是父进程,id:%d\n",getpid());

      printf("-----i=%d-----\n",i);

    }

    exit(0);

}

子进程在打印第一句时,父进程也在打印第一句,但是子进程在执行第二句时,父进程已经直接over了(这只是个简单的说法,实际过程可能并不如此,我要说的是,父进程先于子进程的打印语句之前就结束)。因此此时的子进程成了孤儿进程,会被init也就是1号进程领养,成为init的子进程。 为了避免这样的情况,父进程最后可以执行wait来等待子进程的返回。
3. 用vfork()创建子进程,执行后程序一直不断地重复运行,不断创建子进程,结尾用exit(0)代替return(0)后问题就能解决
return 0在一个函数中是正常的返回过程,它会使得程序返回到函数被调用处,回复之前的执行流程,return 语句不会被执行。而exit 一般是在任意位置和使用的,执行到exit 0时,整个进程就over了(这也是为什么在多线程程序中不要随意使用exit的原因),用来使程序退出运行,一般用来处理(不可挽回的)错误状态。

?

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

  

int main()

{

  int i=0;

  pid_t pid;

  printf("还没创建子进程\n");

  i++;

  pid = vfork();

  if(pid==-1)

  {

    printf("fork error!\n");

  }

  else if(pid==0)

  {

    i++;

    printf("我是子进程,id%d\n",getpid());

    printf("我的父亲是id:%d\n",getppid());

    printf("-----i=%d-----\n",i);

  }

  else

  {

    i++;

    printf("我是父进程,id:%d\n",getpid());

    printf("-----i=%d-----\n",i);

  }

  return(0); 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_27320195/article/details/85236873

智能推荐

AVFrame&AVPacket_天天av-程序员宅基地

文章浏览阅读1.5w次。AVFrame:( This structure describes decoded (raw) audio or video data. AVFrame must be allocated using av_frame_alloc(). Note that this only allocates the AVFrame itself, the buffers for the data mus_天天av

Java经典例题07:用100元人民币兑换10元、5元、1元的纸币_编程把100元换成1元5元10元-程序员宅基地

文章浏览阅读3.5k次,点赞2次,收藏12次。解题思路分析:1.100元兑换10元纸币,可以兑换10张,但每种纸币都要有,所以最多只能兑换9张,最少兑换1张。则初始值为1;循环条件小于10或者小于等于9。2.100元兑换5元纸币,可以兑换20,但每种纸币都要有,所以最多只能兑换19张,最少兑换1张。初始值为1;循环条件小于20或者小于等于19。3.100元兑换1元纸币,可以兑换100张,但每种纸币都要有,所以最多只能兑换99张,最少兑换1张。则初始值为1;循环条件小于100或者小于等于99。_编程把100元换成1元5元10元

猜三次年龄_找人猜三次年龄-程序员宅基地

文章浏览阅读450次。1、允许用户最多尝试三次2、每尝试三次后,如果还没猜对,就问用户是否继续玩,如果回答Y,y,就继续猜三次,以此往复,如果回答N,n,就直接退出times=0count=3while times<=3:age=int(input(‘请输入年龄:’))if age == 18:print(‘猜对了’)breakelif age > 18:print(‘猜大了’)else:print(‘猜小了’)times+=1if times3:choose = input(‘继续猜Y_找人猜三次年龄

SDOI2017 Round2 详细题解-程序员宅基地

文章浏览阅读152次。这套题实在是太神仙了。。做了我好久。。。好多题都是去搜题解才会的 TAT。剩的那道题先咕着,如果省选没有退役就来填吧。「SDOI2017」龙与地下城题意丢 \(Y\) 次骰子,骰子有 \(X\) 面,每一面的概率均等,取值为 \([0, X)\) ,问最后取值在 \([a, b]\) 之间的概率。一个浮点数,绝对误差不超过 \(0.013579\) 为正确。数据范围每组数据有 \...

嵌入式数据库-Sqlite3-程序员宅基地

文章浏览阅读1.1k次,点赞36次,收藏25次。阅读引言: 本文将会从环境sqlite3的安装、数据库的基础知识、sqlite3命令、以及sqlite的sql语句最后还有一个完整的代码实例, 相信仔细学习完这篇内容之后大家一定能有所收获。

C++ Builder编写WinForm从Web服务器下载文件-程序员宅基地

文章浏览阅读51次。UnicodeString templateSavePath = ChangeFileExt(ExtractFilePath(Application->ExeName),"tmp.doc");IdAntiFreeze1->OnlyWhenIdle = false;//设置使程序有反应.TMemoryStream *templateStream ;templateStre..._c++webserver下载文件

随便推点

JAVA小项目潜艇大战_java潜艇大战-程序员宅基地

文章浏览阅读8.3k次,点赞10次,收藏41次。一、第一天1、创建战舰、侦察潜艇、鱼雷潜艇、水雷潜艇、水雷、深水炸弹类完整代码:package day01;//战舰public class Battleship { int width; int height; int x; int y; int speed; int life; void move(){ System.out.println("战舰移动"); }}package day01;//侦察潜艇_java潜艇大战

02表单校验的基本步骤-程序员宅基地

文章浏览阅读940次。表单校验的基本步骤_表单校验

libOpenBlas.dll缺失依赖解决办法-程序员宅基地

文章浏览阅读4.5k次。libOpenBlas.dll缺失依赖解决办法 intellij idea 1.dll文件缺失依赖,报错:“找不到指定模块”2.下载depends查看dll缺失文件3.下载缺失依赖libopenblas.dll出错起因由于java web项目需要调用openBlas库来进行运算,就下载了预编译的libopenblas文件进行调用,首先遇到路径出错问题、之后又是dll文件缺失依赖问题,以下是解决..._libopenblas.dll

Swoole 实践篇之结合 WebSocket 实现心跳检测机制-程序员宅基地

文章浏览阅读251次,点赞3次,收藏10次。这里实现的心跳检测机制是一个基础版的,心跳包的主要作用是用于检测用户端是否存活,有助于我们及时判断用户端是否存在断线的问题。在我之前开发过的项目中,有一个基于物联网在线直播抓娃娃的项目,其中就有需要实时监控设备在线状态的需求,该需求就是使用心跳包来实现的。实际上心跳检测技术,应用更广泛的是实时通信、或设备管理的场景偏多。

Maven dependency scope_maven dependent scope-程序员宅基地

文章浏览阅读714次。Dependency scope is used to limit the transitivity of a dependency, and also to affect the classpath used for various build tasks.There are 6 scopes available:compileThis is the default scop_maven dependent scope

TCP头部结构信息_tcp头部包含哪些信息-程序员宅基地

文章浏览阅读3.6k次。TCP 头部结构信息_tcp头部包含哪些信息