Windows下return exit code 13,exit和ExitProcess的区别和分析

main函数中exit(0)和return(0)的区别。(linux下c编程)
[问题点数:40分,结帖人yyhhjjcc]
main函数中exit(0)和return(0)的区别。(linux下c编程)
[问题点数:40分,结帖人yyhhjjcc]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2013年7月 Linux/Unix社区大版内专家分月排行榜第二2012年6月 Linux/Unix社区大版内专家分月排行榜第二2011年5月 Linux/Unix社区大版内专家分月排行榜第二2011年4月 Linux/Unix社区大版内专家分月排行榜第二2011年3月 Linux/Unix社区大版内专家分月排行榜第二2010年10月 Linux/Unix社区大版内专家分月排行榜第二2010年9月 Linux/Unix社区大版内专家分月排行榜第二
2011年9月 Linux/Unix社区大版内专家分月排行榜第三2010年12月 Linux/Unix社区大版内专家分月排行榜第三2010年11月 Linux/Unix社区大版内专家分月排行榜第三2010年9月 C/C++大版内专家分月排行榜第三
2008年3月 Linux/Unix社区大版内专家分月排行榜第二
2012年9月 Linux/Unix社区大版内专家分月排行榜第三2007年6月 Linux/Unix社区大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。1,exit用于在程序运行的过程中随时结束程序,exit的参数是返回给OS的。main函数结束时也会隐式地调用exit函数。exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件。exit是结束一个进程,它将删除进程使用的内存空间,同时把错误信息返回父进程,而return是返回函数值并退出函数2,return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。3,exit函数是退出应用程序,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息。4,和机器和操作系统有关一般是 0 为正常退出 非0 为非正常退出5,void exit(int status);6,atexit()函数的参数是一个函数指针,函数指针指向一个没有参数也没有返回值的函数。atexit()的函数原型是:int atexit (void (*)(void));在一个程序中最多可以用atexit()注册32个处理函数,这些处理函数的调用顺序与其注册的顺序相反,也即最先注册的最后调用,最后注册的最先调用。
一般程序执行到 main() 的结束就完成了, 如果想在程序结束时做一些事情, 可以尝试着用这个函数.
void f1(void)
printf("exit f1/n");
void f2(void)
printf("exit f2/n");
int main()
atexit(f1);
atexit(f2);
printf("exit main/n");
return是返回调用函数,exit是退出进程, 你可以 man 3 exit return是从A城市中的x小区到y小区,&&Exit&走出A城
在main函数里面return(0)和exit(0)是一样的,子函数用return返回;而子进程用exit退出,调用exit时要调用一段终止处理程序,然后关闭所有I/O流。
exit本身不是系统调用,而是一个C标准库的函数而已,在stdlib里面,系统调用是exit内部实现去完成的。
在main函数中我们通常使用return (0);这样的方式返回一个值。但这是限定在非void情况下的也就是void main()这样的形式。exit()通常是用在子程序中用来终结程序用的,使用后程序自动结束跳会操作系统。但在如果把exit用在main内的时候无论main是否定义成void返回的值都是有效的,并且exit不需要考虑类型,exit(1)等价于return (1)
MS的msdn中关于atexit的help如下:
Processes the specified function at exit.
int atexit(void (__cdecl *func )( void )
阅读(...) 评论()Windows下return,exit和ExitProcess的区别和分析- -
编辑:www.fx114.net
本篇文章主要介绍了"Windows下return,exit和ExitProcess的区别和分析- - ",主要涉及到Windows下return,exit和ExitProcess的区别和分析- - 方面的内容,对于Windows下return,exit和ExitProcess的区别和分析- - 感兴趣的同学可以参考一下。
&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
通常,我们为了使自己的程序结束,会在主函数中使用return或调用exit()。在windows下还有ExitProcess()和TerminateProcess()等函数。
本文的目的是比较以上几种结束程序的方式的区别,并分析其原理。
首先我们用一个例子来说明几种结束方式的区别。
测试环境为Windows XP HOME SP2,编译器为Visual Studio.net 2003
测试代码如下:
#include
#include
#include
class Test
{
public:
&Test (int i) {m_i=i; printf ('construct %dn', m_i);};
&~Test () {printf ('destruct %dn', m_i);};
private:
&int m_i;
};
Test t_1 (1);
int main(int argc, char* argv[])
{
&Test t_2 (2);
&printf('Hello World!n');
//&return 0;
//&exit (0);
//&ExitProcess (0);
}
我们的目标是察看两种结束方式有什么不同。
程序在运行的结果为:
使用return 0结束时:
construct 1
construct 2
Hello World!
destruct 2
destruct 1
使用exit (0)结束时:
construct 1
construct 2
Hello World!
destruct 1
使用ExitProcess (0)结束时:
construct 1
construct 2
Hello World!
从结果上我们可以看出来,采用return来结束进程可以正确的析构全局和局部对象。而采用exit()来结束进程时全局对象可以正确析构,但局部对象没有正确析构。采用ExitProcess(0)结束时全局和局部对象都没有正确析构。
为什么会出现这样的情况呢?
《Windows核心编程》中我们可以得到以下解释:
'当主线程的进入点函数(WinMain、wWinMain、main或wmain)返回时,它将返回给C/C++运行期启动代码,它能够正确地清楚该进程使用的所有C运行期资源。当C运行期资源被释放之后,C运行期启动代码就显式的调用ExitProcess,并将进入点函数返回的值传递给它。'
那么,通过跟踪代码我们可以发现:
return 0实际上执行了以下操作:
&return 0;
& mov&&&&&&&& dword ptr [ebp-0D4h],0
0040103F& lea&&&&&&&& ecx,[t_2]
& call&&&&&&& Test::~Test (4010F0h)
& mov&&&&&&&& eax,dword ptr [ebp-0D4h]
}
0040104D& push&&&&&&& edx&
0040104E& mov&&&&&&&& ecx,ebp
& push&&&&&&& eax&
& lea&&&&&&&& edx,ds:[401072h]
& call&&&&&&& _RTC_CheckStackVars (4011E0h)
0040105C& pop&&&&&&&& eax&
0040105D& pop&&&&&&&& edx&
0040105E& pop&&&&&&&& edi&
0040105F& pop&&&&&&&& esi&
& pop&&&&&&&& ebx&
& add&&&&&&&& esp,0D8h
& cmp&&&&&&&& ebp,esp
& call&&&&&&& _RTC_CheckEsp (4011B0h)
0040106E& mov&&&&&&&& esp,ebp
& pop&&&&&&&& ebp&
& ret&&&&&&&&&&&&&
在ret之后,程序返回到启动main函数的代码,并执行以下操作:
&&&&&&&&&&& if ( !managedapp )
&&&&&&&&&&&&&&& exit(mainret);
&&&&&&&&&&& _cexit();
可见return 0上调用了局部对象t_2的析构函数。

void __cdecl exit (
&&&&&&& int code
&&&&&&& )
{
&&&&&&& doexit(code, 0, 0); /* full term, kill process */
}
void __cdecl _cexit (
&&&&&&& void
&&&&&&& )
{
&&&&&&& doexit(0, 0, 1);&&& /* full term, return to caller */
}
&&&&&&&&&
实际上程序调用了doexit函数。
static void __cdecl doexit (
&&&&&&& int code,
&&&&&&& int quick,
&&&&&&& int retcaller
&&&&&&& )
{
#ifdef _DEBUG
&&&&&&& static int fExit = 0;
#endif& /* _DEBUG */
#ifdef _MT
&&&&&&& _lockexit();&&&&&&& /* assure only 1 thread in exit path */
&&&&&&& __TRY
#endif& /* _MT */
&&&&&&&&&&& if (_C_Exit_Done == TRUE)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& /* if doexit() is being called recursively */
&&&&&&&&&&&&&&&&&&& TerminateProcess(GetCurrentProcess(),code);&&&& /* terminate with extreme prejudice */
&&&&&&&&&&& _C_Termination_Done = TRUE;
&&&&&&&&&&& /* save callable exit flag (for use by terminators) */
&&&&&&&&&&& _exitflag = (char)& /* 0 = term, !0 = callable exit */
&&&&&&&&&&& if (!quick) {
&&&&&&&&&&&&&&& /*
&&&&&&&&&&&&&&&& * do _onexit/atexit() terminators
&&&&&&&&&&&&&&&& * (if there are any)
&&&&&&&&&&&&&&&& *
&&&&&&&&&&&&&&&& * These terminators MUST be executed in reverse order (LIFO)!
&&&&&&&&&&&&&&&& *
&&&&&&&&&&&&&&&& * NOTE:
&&&&&&&&&&&&&&&& *& This code assumes that __onexitbegin points
&&&&&&&&&&&&&&&& *& to the first valid onexit() entry and that
&&&&&&&&&&&&&&&& *& __onexitend points past the last valid entry.
&&&&&&&&&&&&&&&& *& If __onexitbegin == __onexitend, the table
&&&&&&&&&&&&&&&& *& is empty and there are no routines to call.
&&&&&&&&&&&&&&&& */
&&&&&&&&&&&&&&& if (__onexitbegin) {
&&&&&&&&&&&&&&&&&&& while ( --__onexitend &= __onexitbegin )
&&&&&&&&&&&&&&&&&&& /*
&&&&&&&&&&&&&&&&&&&& * if current table entry is non-NULL,
&&&&&&&&&&&&&&&&&&&& * call thru it.
&&&&&&&&&&&&&&&&&&&& */
&&&&&&&&&&&&&&&&&&& if ( *__onexitend != NULL )
&&&&&&&&&&&&&&&&&&&&&&& (**__onexitend)();
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& /*
&&&&&&&&&&&&&&&& * do pre-terminators
&&&&&&&&&&&&&&&& */
&&&&&&&&&&&&&&& _initterm(__xp_a, __xp_z);
&&&&&&&&&&& }
&&&&&&&&&&& /*
&&&&&&&&&&&& * do terminators
&&&&&&&&&&&& */
&&&&&&&&&&& _initterm(__xt_a, __xt_z);
#ifndef CRTDLL
#ifdef _DEBUG
&&&&&&&&&&& /* Dump all memory leaks */
&&&&&&&&&&& if (!fExit && _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& fExit = 1;
&&&&&&&&&&&&&&& _CrtDumpMemoryLeaks();
&&&&&&&&&&& }
#endif& /* _DEBUG */
#endif& /* CRTDLL */
&&&&&&&&&&& /* return to OS or to caller */
#ifdef _MT
&&&&&&& __FINALLY
&&&&&&&&&&& if (retcaller)
&&&&&&&&&&&&&&& _unlockexit();&&&&& /* unlock the exit code path */
&&&&&&& __END_TRY_FINALLY
#endif& /* _MT */
&&&&&&& if (retcaller)
&&&&&&&&&&&
&&&&&&& _C_Exit_Done = TRUE;
&&&&&&& __crtExitProcess(code);
}
其中部分源代码如下:
&&&&&&&&&&&&&&& if (__onexitbegin) {
& cmp&&&&&&&& dword ptr [___onexitbegin (412DA8h)],0
0040605D& je&&&&&&&&& doexit+70h (406090h)
&&&&&&&&&&&&&&&&&&& while ( --__onexitend &= __onexitbegin )
0040605F& mov&&&&&&&& edx,dword ptr [___onexitend (412DA4h)]
& sub&&&&&&&& edx,4
& mov&&&&&&&& dword ptr [___onexitend (412DA4h)],edx
0040606E& mov&&&&&&&& eax,dword ptr [___onexitend (412DA4h)]
& cmp&&&&&&&& eax,dword ptr [___onexitbegin (412DA8h)]
& jb&&&&&&&&& doexit+70h (406090h)
&&&&&&&&&&&&&&&&&&& /*
&&&&&&&&&&&&&&&&&&&& * if current table entry is non-NULL,
&&&&&&&&&&&&&&&&&&&& * call thru it.
&&&&&&&&&&&&&&&&&&&& */
&&&&&&&&&&&&&&&&&&& if ( *__onexitend != NULL )
0040607B& mov&&&&&&&& ecx,dword ptr [___onexitend (412DA4h)]
& cmp&&&&&&&& dword ptr [ecx],0
& je&&&&&&&&& doexit+6Eh (40608Eh)
&&&&&&&&&&&&&&&&&&&&&&& (**__onexitend)();
& mov&&&&&&&& edx,dword ptr [___onexitend (412DA4h)]
0040608C& call&&&&&&& dword ptr [edx]
&&&&&&&&&&&&&&& }
0040608E& jmp&&&&&&&& doexit+3Fh (40605Fh)
程序在0040608C处跳转到如下代码:
<font color="#40EC10& push&&&&&&& ebp&
0040EC11& mov&&&&&&&& ebp,esp
0040EC13& sub&&&&&&&& esp,0C0h
0040EC19& push&&&&&&& ebx&
0040EC1A& push&&&&&&& esi&
0040EC1B& push&&&&&&& edi&
0040EC1C& lea&&&&&&&& edi,[ebp-0C0h]
0040EC22& mov&&&&&&&& ecx,30h
0040EC27& mov&&&&&&&& eax,0CCCCCCCCh
0040EC2C& rep stos&&& dword ptr [edi]
0040EC2E& mov&&&&&&&& ecx,offset t_1 (412760h)
0040EC33& call&&&&&&& Test::~Test (4010F0h)
0040EC38& pop&&&&&&&& edi&
0040EC39& pop&&&&&&&& esi&
0040EC3A& pop&&&&&&&& ebx&
0040EC3B& add&&&&&&&& esp,0C0h
0040EC41& cmp&&&&&&&& ebp,esp
0040EC43& call&&&&&&& _RTC_CheckEsp (4011B0h)
0040EC48& mov&&&&&&&& esp,ebp
0040EC4A& pop&&&&&&&& ebp&
0040EC4B& ret&&&&&&&&&&&&&
在这里,全局变量t_1被析构。
在doexit的最后,程序调用
&&&&&&& __crtExitProcess(code);
void __cdecl __crtExitProcess (
&&&&&&& int status
&&&&&&& )
{
&&&&&&& HMODULE
&&&&&&& PFN_EXIT_PROCESS
&&&&&&& hmod = GetModuleHandle('mscoree.dll');
&&&&&&& if (hmod != NULL) {
&&&&&&&&&&& pfn = (PFN_EXIT_PROCESS)GetProcAddress(hmod, 'CorExitProcess');
&&&&&&&&&&& if (pfn != NULL) {
&&&&&&&&&&&&&&& pfn(status);
&&&&&&&&&&& }
&&&&&&& }
&&&&&&& /*
&&&&&&&& * Either mscoree.dll isn't loaded,
&&&&&&&& * or CorExitProcess isn't exported from mscoree.dll,
&&&&&&&& * or CorExitProcess returned (should never happen).
&&&&&&&& * Just call ExitProcess.
&&&&&&&& */
&&&&&&& ExitProcess(status);
}
在这里,终于调用到了ExitProcess。至此,全局对象t_1和局部对象t_2都完成了析构操作。
从分析过程,我们可以得出以下结论。
在Windows下,return 0 的实际执行过程是:
先析构main函数内的局部对象。
返回至调用main的函数。
调用exit函数,由exit函数调用doexit函数,在doexit函数中完成对全局对象的析构。
最后调用ExitProcess结束进程。
所以,ExitProcess不负责任何对象的析构,exit只负责析构全局对象,return 0可以析构局部对象并调用exit,因此能析构全部对象。
如果您觉得这篇文章对您有帮助,欢迎使用支付宝对我们捐助。
本文标题:
本页链接:浅谈windows下基于Qemu Manager 虚拟机安装 linux 等操作系统的方法_-IT行业第一站
浅谈windows下基于Qemu Manager 虚拟机安装 linux 等操作系统的方法
标题:浅谈windows下基于Qemu Manager 虚拟机安装 linux 等操作系统的方法
浅谈下基于虚拟机安装 等操作系统的方法
&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&& --马志晶
QEMU Windows
VPC VMwareQemu
Accelerator
WinImage, UltraISO, WinISO, Alcohol, cdrtools
WinImage-v8.10.8100
OK 光驱中插入linux系统盘
:linux.iso .iso
[url]http://www.h7.dion.ne.jp/~qemu-win/[/url]
qemu-img.exe(kouge.img), 10G,
, 10G, 4k. solaris.img
Qemu OpenSolaris , 10G ,
3. cmd dos
&qemu-img.exe create kouge.img 10G
如图1(附件1)
4. , :Li nux,Unix ,BSD, PHP, Apac h,asp,,@/j1
&qemu.exe -L . -m 512 -boot d -hda kouge.img -cdrom kouge.iso
PDF "pdfFactory Pro" [url][/url]
-m : (Mbyte)tech.techweb. S"W2m'E 6V1[&o s
-boot : (boot device), , floppy(a), hard disk(c),
-hda : (hard disk image)%S W1f z0t
-cdrom : (CD-ROM image)
注意:kqemu kqemu-1.3.0pre7
kqemu.inf -&
net start kqemu
5. . , Enter .
. Ctrl+Alt+2 Qemu , Quit .
&qemu.exe -L . -m 512 -boot c -hda kouge.img
Linux,Unix, BSD,PH P,Apach, asp,,0W B ? B+q
6. linux , .:)
此时安装虚拟机已完成,这样就可以在windows下同时运行linux 操
作系统了,与此相同可以安装其他一些操作系统,对于不同需要的人可以安装多个系统了,真是美斋!
&本文出自 “海之舟” 博客,请务必保留此出处http://mazhijing./44
延伸阅读:
热门搜索:
特色栏目:
类别推荐:收藏,1.2k 浏览
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
最近读 APUE,APUE 7.3 节中说,main 函数 return 相当于
exit(main(argc, argv))
但是在实践程序 8-2 时候出现了问题
下面的程序编译后执行会 core-dump
#include &stdio.h&
#include &stdlib.h&
#include &unistd.h&
int glob = 6;
main(void)
printf("before vfork\n");
if ((pid = vfork()) & 0) {
printf("vfork error");
} else if (pid == 0) {
/* 子进程 */
//exit(0);
printf("pid=%d, glob=%d, var=%d\n", getpid(), glob, var);
//exit(0);
但是将 return 改为 exit 后却不会
#include &stdio.h&
#include &stdlib.h&
#include &unistd.h&
int glob = 6;
main(void)
printf("before vfork\n");
if ((pid = vfork()) & 0) {
printf("vfork error");
} else if (pid == 0) {
/* 子进程 */
//return 0;
printf("pid=%d, glob=%d, var=%d\n", getpid(), glob, var);
//return 0;
请问是什么样的原因导致第一段程序会出 core-dump 呢?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
The vfork() function has the same effect as fork(2),
except that the behavior is undefined if the process created by
vfork() either modifies any data other than a variable of type pid_t
used to store the return value from vfork(), or returns from the
function in which vfork() was called, or calls any other function
before successfully calling _exit(2) or one of the exec(3) family of
functions.
直接return是一个undefined行为. 发生core-dump是正常的.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
Look ! when use the 'return' at the end of code !You will probly see it (as the picture show)
If you see those code do not help ...just let me know
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
摘录一段《C语言程序设计-现代方法》9.5章节
return语句和exit函数之间的差异是:不管哪个函数调用exit函数都会导致程序终止,return语句仅当由main函数调用时才会导致程序终止。
PS:你的代码貌似有问题(我在printf上加了计数)
printf("pid=%d, glob=%d, var=%d -&%d&--\n", getpid(), glob, var, ++i);
当使用return 0的时候,运行结果是这样的:
before vfork
pid=5101, glob=31853, var=- -&31847&--
before vfork
pid=5101, glob=31854, var=- -&31848&--
before vfork
pid=5101, glob=31855, var=- -&31849&--
before vfork
然后停止了
而使用exit 0时,是这样的:
straysh Learning]$./a.out
before vfork
pid=5145, glob=7, var=4195680 -&1&--
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
13 小时前 回答
exit是程序退出,无论在什么函数中调用都会退出,程序退出时,对相应的资源如文件描述符,缓冲区等进行回收。但是return函数退出。假如main函数调用了一个函数func(),在func中使用了return,则程序从func中返回到main中继续执行。但是如果在func中调用exit,则程序会终止退出。所以在main中使用exit和return,由于只有一层函数调用。看上去的效果是一样的。至于fork之后,使用return发生的这种情况就很奇怪了
同步到新浪微博
不要错过该问题的后续解决方案
如果你没找到答案,记得登录关注哦,大家会尽全力帮你解决的 ^___^
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
内容质量差,或不适合在本网站出现
无意义讨论型问题
其他原因(请补充说明)
举报理由:
推广(招聘、广告、SEO 等)方面的内容
带有人身攻击、辱骂、仇恨等违反条款的内容
与已有问题重复(请编辑该提问指向已有相同问题)
内容质量差,或不适合在本网站出现
答非所问,不符合答题要求
其他原因(请补充说明)
补充说明:

我要回帖

更多关于 nodejs process.exit 的文章

 

随机推荐