linux C编程,return 和exit的区别

never_QL 2008-12-19 03:12:46
相关代码如下

......
int main()
{
pid_t pid;
int number = 1;

pid = vfork();
if(pid == 0)
{
printf("%d\n",number);
number++;
return 0;
// exit(0);
}
printf("%d\n",number);
return 0;
}


我知道vfork会阻塞父进程,以保证子进程先运行。
现在出现的情况是,当在子进程中用return 0;结束子进程时之后,继续执行父进程会有错误数据被输出来。
但用exit(0);时,整个程序都输出正常。

我的问题,为什么用return 0和exit(0)会不一样?
在这个程序中,它们有什么区别?
谢谢
...全文
1186 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
mymtom 2008-12-30
  • 打赏
  • 举报
回复
这个没有什么好说的,vfork后,在子进程内正确的系统调用只有两个选择:exec和_exit.
return会返回到并不存在的stack frame.
exit会刷新和关闭标准IO,这会破坏父进程的标准IO数据结构。

以上这些都是在vfork手册页里的。
http://www.opengroup.org/onlinepubs/009695399/functions/vfork.html
dog250 2008-12-26
  • 打赏
  • 举报
回复
和io没有关系,关键是父子进程共享了堆栈,而return会改变堆栈,因此子进程的return会破坏栈结构,故而出错
kaifadawang 2008-12-25
  • 打赏
  • 举报
回复
return和exit的区别以及为什么vfork的子进程不能return http://devcool.cn devcool编写 2008-12-24

exit()用于退出整个程序,也就是说它将控制权交给操作系统。

在执行了exit()后,所有的内存和临时存储区会被刷新,所有的文件会被关闭,控制权不再在程序这里,exit()还会调用终止处理程序,可以用atexit函数来注册一个终止处理程序,将来在exit()中会被调用。多次调用exit()函数,行为是未定义的,这种情况我们基本不用操心。和exit()类似的 _exit()和_Exit()函数不会处理这些任务,直接将控制权交给操作系统。相比较,return()语句是从函数返回,并且将控制权交给调用函数。注意这里return仅仅是从函数返回,去交还控制权,在return和交换控制权期间会发生一些事情。交出控制权后又干了什么和return没关系了。
先看一个简单的c++ 程序:

#include <iostream>

using namespace std;

class A
{
public:
~A();
};

A::~A()
{
cout << "good bye" << endl;
}

int main()
{
A a;
return 0;
//exit(0);
}

在上面的程序中,如果是return 0,那么A的析构函数会被执行,从而输出good bye。如果换了exit(0),则不会输出good bye。这说明了exit()函数被调用后就开始执行相关清理工作,然后把控制权交给了操作系统。而return执行后,会有退栈的过程,从而A的析构函数会被执行。return从main返回后,通常也会执行exit()。在c++中请不要随便使用exit()函数。

再看一个vfork的例子:

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

int main()
{
pid_t pid;
pid = vfork();
if(pid == 0)
{
printf("child\n");
return 0;
//exit(0);
}
printf("parent\n");
return 0;
}

在上面的例子中,如果在子进程部分使用return 0,系统将报错,如果使用exit(0),系统正常。
这是由于return语句改变了当前的栈空间,但对于vfork来说,很多的实现为了提高效率不会复制父进程的栈空间,而是和父进程共享。在子进程中使用return后,父进程的栈空间就会发生变化,当父进程返回的时候系统就会报错。而exit函数不会。
下面是在freeBSD下 man vfork后出现的一句话:
It does not work, however, to return while running in the child's context from the procedure that called vfork() since the eventual return from vfork() would then return to a no longer existent stack frame.

注:以上内容为个人研究,不保证完全正确
outblue 2008-12-25
  • 打赏
  • 举报
回复
学习了
  • 打赏
  • 举报
回复
学习的
happyzhangyz 2008-12-23
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 guosha 的回复:]
我来说说,抛砖引玉。

vfork()跟fork()不同不只是你说的阻塞父进程直到子进程调用_exit或是exec, vfork()产生的子进程会跟父进程完全使用相同的内存空间。所以你子过程里改了父进程的变量,应该是会在父进程里反映出来的。所以子进程里return返回时,后面会输出2这很正常。

另外你看一个vfork的man page,"Be careful, also, to call _exit rather than exit if you can't execve, since exit will flush and close standar…
[/Quote]
这个正解吧
wangkongxinglang 2008-12-23
  • 打赏
  • 举报
回复
两个结果应该一样
return返回正确结果
其实就是调用exit 0
du198710 2008-12-23
  • 打赏
  • 举报
回复
我曾经测试过和你一模一样的代码(一本书上的例子),也发现这个问题,我觉得应该是父进程在等待子进程结束,exit把子进程结束了以后父进程的数据就对了~
outblue 2008-12-19
  • 打赏
  • 举报
回复
是挺奇怪的,exit和_exit不同这是众所周知的,这个地方用_exit肯定会得到正确结果的,但用return和exit的结果不一样还真是让人费解啊。
threeleafzerg007 2008-12-19
  • 打赏
  • 举报
回复
up 2nd floor.
快乐田伯光 2008-12-19
  • 打赏
  • 举报
回复
一般来说你使用vfork时应该是立刻进行exec,而不能去读写任何原来父进程存的数据。
快乐田伯光 2008-12-19
  • 打赏
  • 举报
回复
我来说说,抛砖引玉。

vfork()跟fork()不同不只是你说的阻塞父进程直到子进程调用_exit或是exec, vfork()产生的子进程会跟父进程完全使用相同的内存空间。所以你子过程里改了父进程的变量,应该是会在父进程里反映出来的。所以子进程里return返回时,后面会输出2这很正常。

另外你看一个vfork的man page,"Be careful, also, to call _exit rather than exit if you can't execve, since exit will flush and close standard I/O channels, and thereby mess up the parent processes standardI/O data structures."
里面说,vfork最终应该是要么掉用_exit要么掉用exec, 而不应该掉用exit(), 因为exit会有刷新流和关闭标准输入输出的动作,从而会影响父进程里标准IO库的管理数据结构,从面导致出错。

我刚才试了一下,换exit为_exit结果是跟return 0是一样的。
houhou_houhou 2008-12-19
  • 打赏
  • 举报
回复
exit(0)就是表示程序正常结束啊,所以输出当然正常了

23,118

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧