Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8139377
  • 博文数量: 594
  • 博客积分: 13065
  • 博客等级: 上将
  • 技术积分: 10324
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-26 16:44
个人简介

推荐: blog.csdn.net/aquester https://github.com/eyjian https://www.cnblogs.com/aquester http://blog.chinaunix.net/uid/20682147.html

文章分类

全部博文(594)

分类: C/C++

2019-01-29 11:21:27

 

main函数中,returnexit经常混用,两者的一个区别: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

 

阅读(7695) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~