return和exit

来源:互联网 发布:网络歌手灰色天空 编辑:程序博客网 时间:2024/05/18 02:01

return和exit

标签(空格分隔): APUE


  在每个函数结束之后,习惯上都会return一下。而在main函数里面,既可以用return,也可以用exit来结束进程。现在来看看return到底做了什么。
  先写一个简单的C程序:

#include<stdio.h>int add(int ,int);int main(){    int a = 1;    int b = 2;    int c = add(a, b);    return 1;   }int add(int a, int b){    int c =a + b;    return c;}

然后反汇编,看看汇编的东西:

080483ed <main>: 80483ed:   55                      push   %ebp 80483ee:   89 e5                   mov    %esp,%ebp 80483f0:   83 e4 f0                and    $0xfffffff0,%esp 80483f3:   83 ec 20                sub    $0x20,%esp 80483f6:   c7 44 24 14 01 00 00    movl   $0x1,0x14(%esp) 80483fd:   00  80483fe:   c7 44 24 18 02 00 00    movl   $0x2,0x18(%esp) 8048405:   00  8048406:   8b 44 24 18             mov    0x18(%esp),%eax 804840a:   89 44 24 04             mov    %eax,0x4(%esp) 804840e:   8b 44 24 14             mov    0x14(%esp),%eax 8048412:   89 04 24                mov    %eax,(%esp) 8048415:   e8 0b 00 00 00          call   8048425 <add> 804841a:   89 44 24 1c             mov    %eax,0x1c(%esp) 804841e:   b8 00 00 00 00          mov    $0x0,%eax 8048423:   c9                      leave   8048424:   c3                      ret    08048425 <add>: 8048425:   55                      push   %ebp 8048426:   89 e5                   mov    %esp,%ebp 8048428:   83 ec 10                sub    $0x10,%esp 804842b:   8b 45 0c                mov    0xc(%ebp),%eax 804842e:   8b 55 08                mov    0x8(%ebp),%edx 8048431:   01 d0                   add    %edx,%eax 8048433:   89 45 fc                mov    %eax,-0x4(%ebp) 8048436:   8b 45 fc                mov    -0x4(%ebp),%eax 8048439:   c9                      leave   804843a:   c3                      ret        

其他的不用管,只要看两个程序的结尾,可以看到,两个程序最后面的内容。后面如果是有返回值的return,则相当于如下三条指令:

804841e:    b8 00 00 00 00          mov    $0x0,%eax 8048423:   c9                      leave   8048424:   c3                      ret    

第一条指令是给eax寄存器附上返回值,后面的两条指令,相当于:

mov %ebp,%esppop %ebppop %rip

稍微有一点寄存器基础的,就知道,这三条指令是函数栈的回收。即return就是函数栈的回收指令。

下面再来看下exit。
和上面一样的程序,只是在main里面用exit(0)来退出程序。反汇编得到的汇编如下:

0804841d <main>: 804841d:   55                      push   %ebp 804841e:   89 e5                   mov    %esp,%ebp 8048420:   83 e4 f0                and    $0xfffffff0,%esp 8048423:   83 ec 20                sub    $0x20,%esp 8048426:   c7 44 24 14 01 00 00    movl   $0x1,0x14(%esp) 804842d:   00  804842e:   c7 44 24 18 02 00 00    movl   $0x2,0x18(%esp) 8048435:   00  8048436:   8b 44 24 18             mov    0x18(%esp),%eax 804843a:   89 44 24 04             mov    %eax,0x4(%esp) 804843e:   8b 44 24 14             mov    0x14(%esp),%eax 8048442:   89 04 24                mov    %eax,(%esp) 8048445:   e8 10 00 00 00          call   804845a <add> 804844a:   89 44 24 1c             mov    %eax,0x1c(%esp) 804844e:   c7 04 24 00 00 00 00    movl   $0x0,(%esp) 8048455:   e8 a6 fe ff ff          call   8048300 <exit@plt>

可以看到和上面不一样的是:

 804844e:   c7 04 24 00 00 00 00    movl   $0x0,(%esp) 8048455:   e8 a6 fe ff ff          call   8048300 <exit@plt>

他把esp所指向的地址里面的内容改为了0,然后调用exit。这里和上面的return不一样的是,他没有摧毁栈,然后返回上一级函数。
  而exit()的作用是调用_exit()或者_Exit()系统调用,来直接结束进程。
  
  再来说下atexit()函数。
  int atexit(void (*func) (void));
  通俗来说,atexit函数是一个终止处理程序,他登记那些想在退出main函数之后,再执行的函数,这些函数会在exit()函数中被调用。这里要注意两点:1.登记的函数只能是无输入无输出的函数。2.最后在exit函数中,调用终止处理程序的顺序和登记的时候是相反的。
  关于第二点函数执行顺序的原因说一下自己的猜想:感觉应该是在atexit函数执行的时候,只是把函数指针压入exit的函数栈里面,所以根据栈的特性,最后的执行顺序和压入顺序是反的。
  看一下例子:

#include<stdio.h>#include<stdlib.h>void print1(){    printf("exit1\n");    }void print2(){    printf("exit2\n");}int main(){    atexit(print1);    atexit(print1);    atexit(print2);     return 0;}

结果是:
此处输入图片的描述

可以看到他的执行顺序是反过来的。而且注意,在C程序里面,最后的返回是用的return而不是exit。而终止处理程序实在exit函数里面掉用的。所以简单来说,在main函数里面return到了main函数的上层函数,在上层函数里面依旧调用了exit函数。

总结return和exit:
return只是一个销毁函数栈的指令,在销毁函数栈之后,会调到调用函数中去。而exit是三个作用:执行终止处理程序(注意执行顺序),清理标准I/O,调用_exit或者_Exit系统调用,结束进程。
而在非main函数中,一般使用return,因为exit直接就销毁进程了。
在main函数中,return会把main的栈给销毁掉,在回到上层调用函数,在上层调用函数里面会执行exit()函数来销毁进程。exit就不会销毁main的栈,而是直接就销毁进程。

0 0
原创粉丝点击