专栏首页蓝天C++中的return和exit区别

C++中的return和exit区别

在main函数中,return和exit经常混用,两者的一个区别:return会执行statck unwinding,而exit不会。如果触发了信号,exit也同样不会做stack unwinding,除此之外异常如果没有相应的catch,也同样不会有栈展开(stack unwinding)。

原因是C++编译器只会在遇到“}”或“return”时,才会安插栈展开代码,对于exit等则没这回事。

#include
#include
#include
class X
{
public:
X(int m): _m(m) { printf("X::ctor:%d\n", m); }
~X() { printf("X::dtor:%d\n", _m); }
private:
int _m;
};
int main()
{
X x(1);
#if USE_EXIT
exit(0);
#if USE_RAISE
raise(SIGSEGV);
#else
return 0;
#endif
}

以上述代码为例,通过汇编,可很容易看出这两者的区别:

1) return代码

int main()
{
X x(1);
return(0);
}

反汇编main函数,可以看到有调用~X:

0x08048474 <main+0>:    lea    0x4(%esp),%ecx
0x08048478 :    and    $0xfffffff0,%esp
0x0804847b :    pushl  0xfffffffc(%ecx)
0x0804847e :   push   %ebp
0x0804847f :   mov    %esp,%ebp
0x08048481 :   push   %ebx
0x08048482 :   push   %ecx
0x08048483 :   sub    $0x20,%esp
0x08048486 :   movl   $0x1,0x4(%esp)
0x0804848e :   lea    0xfffffff4(%ebp),%eax
0x08048491 :   mov    %eax,(%esp)
0x08048494 :   call   0x80484b6
0x08048499 :   mov    $0x0,%ebx
0x0804849e :   lea    0xfffffff4(%ebp),%eax
0x080484a1 :   mov    %eax,(%esp)
0x080484a4 :   call   0x80484da <~X>
0x080484a9 :   mov    %ebx,%eax
0x080484ab :   add    $0x20,%esp
0x080484ae :   pop    %ecx
0x080484af :   pop    %ebx
0x080484b0 :   pop    %ebp
0x080484b1 :   lea    0xfffffffc(%ecx),%esp
0x080484b4 :   ret

2) exit代码

int main()
{
X x(1);
exit(0);
}

反汇编main函数,可以看到没有调用~X:

0x080484a4 <main+0>:    lea    0x4(%esp),%ecx
0x080484a8 :    and    $0xfffffff0,%esp
0x080484ab :    pushl  0xfffffffc(%ecx)
0x080484ae :   push   %ebp
0x080484af :   mov    %esp,%ebp
0x080484b1 :   push   %ecx
0x080484b2 :   sub    $0x24,%esp
0x080484b5 :   movl   $0x1,0x4(%esp)
0x080484bd :   lea    0xfffffff8(%ebp),%eax
0x080484c0 :   mov    %eax,(%esp)
0x080484c3 :   call   0x80484d4
0x080484c8 :   movl   $0x0,(%esp)
0x080484cf :   call   0x80483c8 <exit@plt>

附:汇编指令

call指令

分两步: 1) 将当前的IP或CS和IP压入栈中 2) 转移(能实现短转移,它的书写格式同jmp指令)

ret指令

相当于pop IP

retf指令

相当于: 1) pop IP 2) pop CS

lea指令

把操作数OPRD的偏移地址传送到寄存器REG,语法:LEA REG, OPRD

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 命名空间及模块化

    Java用package来达到命名空间同样的效果。 C++就有对应关键字:using namespace。 JavaScript库用对象来封装命名空间。

    城市中的游牧民族
  • 2018年的经历有苦有甜

    2018年每周的任务,目标都通过Trello一直记录着,看板的形式非常直观,目标清晰,同时也能看到自己在某一方面的时间投入和支出。这也是工作之后一直坚持使用...

    程序手艺人
  • 关于Web3D

    逍遥剑客
  • C/C++常见错误汇总

    出错原因: main.cpp中没有找到对应的函数名声明,没有在.cpp引用包含该函数名的头文件.h。 解决方法: 引入对应头文件。

    城市中的游牧民族
  • C++ list

    [work@db-testing-com06-vm3.db01.baidu.com c++]$ g++ -o list list.cpp 

    阳光岛主
  • JNI入门

    首先声明一点,Eclipse不仅仅适合于开发Java应用程序。Eclilpse为Java开发提供了极好的支持,它的设计初衷也是为了Java。但得益于它的设计架构...

    刘晓杰
  • C#脚本实践(三): 集成到游戏

    至此, C#做为脚本已经完全可行了: 可嵌入, 跨平台, 高效率, 热更新, 几乎可以忽略的编译时间, 强大的IDE支持, 丰富的第三方库, 部分动态语言特性的...

    逍遥剑客
  • 从公有云上导镜像导私有云环境

    要求环境上的机器有访问公网的能力,同时安装的docker版本最低为1.12.6,推荐使用的版本为17.12.1(或者以上)

    用户1502070
  • 修复miniblink 文件编码检测和退出内存泄漏的bug

    文本检测的bug原因是我把icu整个都端了,自然icu里检测编码的好用接口也废弃了。不过我扣了一部分出来,用于检测UTF8和GBK编码。剩下的编码,经海绵宝宝

    龙泉寺扫地僧
  • Lua和C如何交互(一)

    全局表中存放了name和hello world的对应关系, 可以通过name在全局表中找到对应的hello world

    程序手艺人

扫码关注云+社区

领取腾讯云代金券