return x与exit(x)到底有什么区别
2016-07-28 16:28
302 查看
return x与exit(x)到底有什么区别书中说main函数return相当于
![](http://s1.51cto.com/wyfs02/M02/85/15/wKiom1eZtWXy1j54AACljl2InyY807.png-wh_500x0-wm_3-wmp_4-s_2033381518.png)
运行结果:
![](http://s1.51cto.com/wyfs02/M01/85/1A/wKiom1eZvyHSkhj6AAAPvSfcC6k003.png-wh_500x0-wm_3-wmp_4-s_1208927181.png)
如果把exit换成return确不会。
基础知识
首先说说fork与vfork的区别
●fork 创建一个进程,并把父进程内存数据copy拷贝到子进程去。
●vfork 创建一个进程,并和父进程的内存数据share一起用。
两个区别是:一个share,一个是copy。
man fork 一下,发现vfork是这样工作的:
(1)保证子进程先执行
(2)当子进程调用exit()或exec()后,父进程往下执行。
那么,为什么那么,要存在vfork?(存在即合理) 原因是这样的——
起初只有fork,但是很多程序在fork一个子进程后就exec一个外部程序,于是fork需要copy父进程的数据这个动作就变得毫无意了,而且还很
重,所以,搞出了个父子进程共享的vfork。所以,vfork本就是为了exec而生。
为什么return会挂掉,exit确不会
从上面我们知道,结束子进程用exit()而不是return,注意,你在vfork中return了,那么,就意味着main函数中retun了,因为父子进程共享函数栈,所以整个函数栈就跪了。
如果在子进程中return了,基本上是一下过程:
子进程的main()函数return了
而main()函数return了,通常会调用exit()或相似的函数。
这时父进程收到子进程exit(),开始从vfork返回,但是此时栈已被破坏,(注:栈会返回一个诡异一个栈地址,对于某些内核版本的实现,直接报“栈错误”就给跪了,然而,对于某些内核版本的实现,于是有可能会再次调用main(),于是进入了一个无限循环的结果,直到vfork 调用返回 error)
如图所示:
![](http://s1.51cto.com/wyfs02/M01/85/1A/wKioL1eZvWjTMhzVAACRC2Wiw0U684.png-wh_500x0-wm_3-wmp_4-s_508410024.png)
总结:returnh会释放局部变量并弹栈,回到上级函数执行,exit()会直接退掉,如果用c++就会知道,return会调用局部对象的析构函数,exit()不会,(注:exit()不是系统调用,是glibc对系统调用 _exit()或_exitgroup()的封装)
可见:子进程调用exit()函数没有修改函数栈,所有,父进程得意顺利执行
exit(main(argc,argv))但实践中出了点问题
![](http://s1.51cto.com/wyfs02/M02/85/15/wKiom1eZtWXy1j54AACljl2InyY807.png-wh_500x0-wm_3-wmp_4-s_2033381518.png)
运行结果:
![](http://s1.51cto.com/wyfs02/M01/85/1A/wKiom1eZvyHSkhj6AAAPvSfcC6k003.png-wh_500x0-wm_3-wmp_4-s_1208927181.png)
如果把exit换成return确不会。
基础知识
首先说说fork与vfork的区别
●fork 创建一个进程,并把父进程内存数据copy拷贝到子进程去。
●vfork 创建一个进程,并和父进程的内存数据share一起用。
两个区别是:一个share,一个是copy。
man fork 一下,发现vfork是这样工作的:
(1)保证子进程先执行
(2)当子进程调用exit()或exec()后,父进程往下执行。
那么,为什么那么,要存在vfork?(存在即合理) 原因是这样的——
起初只有fork,但是很多程序在fork一个子进程后就exec一个外部程序,于是fork需要copy父进程的数据这个动作就变得毫无意了,而且还很
重,所以,搞出了个父子进程共享的vfork。所以,vfork本就是为了exec而生。
为什么return会挂掉,exit确不会
从上面我们知道,结束子进程用exit()而不是return,注意,你在vfork中return了,那么,就意味着main函数中retun了,因为父子进程共享函数栈,所以整个函数栈就跪了。
如果在子进程中return了,基本上是一下过程:
子进程的main()函数return了
而main()函数return了,通常会调用exit()或相似的函数。
这时父进程收到子进程exit(),开始从vfork返回,但是此时栈已被破坏,(注:栈会返回一个诡异一个栈地址,对于某些内核版本的实现,直接报“栈错误”就给跪了,然而,对于某些内核版本的实现,于是有可能会再次调用main(),于是进入了一个无限循环的结果,直到vfork 调用返回 error)
如图所示:
![](http://s1.51cto.com/wyfs02/M01/85/1A/wKioL1eZvWjTMhzVAACRC2Wiw0U684.png-wh_500x0-wm_3-wmp_4-s_508410024.png)
总结:returnh会释放局部变量并弹栈,回到上级函数执行,exit()会直接退掉,如果用c++就会知道,return会调用局部对象的析构函数,exit()不会,(注:exit()不是系统调用,是glibc对系统调用 _exit()或_exitgroup()的封装)
可见:子进程调用exit()函数没有修改函数栈,所有,父进程得意顺利执行
相关文章推荐
- Ruby中require、load、include、extend的区别介绍
- Ruby中的p和puts的使用区别浅析
- Ruby中的block、proc、lambda区别总结
- Redis和Memcached的区别详解
- Lua中调用函数使用点号和冒号的区别
- Lua中关于求模与求余的区别介绍
- TMP、TEMP和TMP文件区别解析
- C#基础语法:结构和类区别详解
- 深入c# 类和结构的区别总结详解
- C#中string.Empty和null的区别详解
- sqlserver和oracle中对datetime进行条件查询的一点区别小结
- 网页中Span和Div的区别
- 大家看了就明白了css样式中类class与标识id选择符的区别小结
- C#中类与结构的区别实例分析
- SQL 中having 和where的区别分析
- c#中(int)、int.Parse()、int.TryParse、Convert.ToInt32的区别详解
- MySQL Antelope和Barracuda的区别分析
- Rails Routes中new、collection、member的区别浅析
- POST与GET方法的区别简要分析
- C#中委托和事件的区别实例解析