C++中的return和exit區別
在main函式中,return和exit經常混用,兩者的一個區別:return會執行statck unwinding,而exit不會。如果觸發了訊號,exit也同樣不會做stack unwinding,除此之外異常如果沒有相應的catch,也同樣不會有棧展開(stack unwinding)。
原因是C++編譯器只會在遇到“}”或“return”時,才會安插棧展開程式碼,對於exit等則沒這回事。
#include <signal.h> #include <stdio.h> #include <stdlib.h>
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 <main+4>: and $0xfffffff0,%esp 0x0804847b <main+7>: pushl 0xfffffffc(%ecx) 0x0804847e <main+10>: push %ebp 0x0804847f <main+11>: mov %esp,%ebp 0x08048481 <main+13>: push %ebx 0x08048482 <main+14>: push %ecx 0x08048483 <main+15>: sub $0x20,%esp 0x08048486 <main+18>: movl $0x1,0x4(%esp) 0x0804848e <main+26>: lea 0xfffffff4(%ebp),%eax 0x08048491 <main+29>: mov %eax,(%esp) 0x08048494 <main+32>: call 0x80484b6 <X> 0x08048499 <main+37>: mov $0x0,%ebx 0x0804849e <main+42>: lea 0xfffffff4(%ebp),%eax 0x080484a1 <main+45>: mov %eax,(%esp) 0x080484a4 <main+48>: call 0x80484da <~X> 0x080484a9 <main+53>: mov %ebx,%eax 0x080484ab <main+55>: add $0x20,%esp 0x080484ae <main+58>: pop %ecx 0x080484af <main+59>: pop %ebx 0x080484b0 <main+60>: pop %ebp 0x080484b1 <main+61>: lea 0xfffffffc(%ecx),%esp 0x080484b4 <main+64>: ret |
2) exit程式碼
int main() { X x(1); exit(0); } |
反彙編main函式,可以看到沒有呼叫~X:
0x080484a4 <main+0>: lea 0x4(%esp),%ecx 0x080484a8 <main+4>: and $0xfffffff0,%esp 0x080484ab <main+7>: pushl 0xfffffffc(%ecx) 0x080484ae <main+10>: push %ebp 0x080484af <main+11>: mov %esp,%ebp 0x080484b1 <main+13>: push %ecx 0x080484b2 <main+14>: sub $0x24,%esp 0x080484b5 <main+17>: movl $0x1,0x4(%esp) 0x080484bd <main+25>: lea 0xfffffff8(%ebp),%eax 0x080484c0 <main+28>: mov %eax,(%esp) 0x080484c3 <main+31>: call 0x80484d4 <X> 0x080484c8 <main+36>: movl $0x0,(%esp) 0x080484cf <main+43>: 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 |
相關文章
- exit和return的區別
- exit(0)與exit(1)、return的區別
- python中 os._exit() 和 sys.exit(), exit(0)的用法和區別Python
- js中return、return true、return false的區別JSFalse
- CSS 中 stopPropagation, preventDefault 和 return false 的區別CSSFalse
- oracle的exit、return、continueOracle
- system.exit(0)和system.exit(1)的區別
- Python教程:return和yield的區別Python
- return,continue和break之間的區別
- onclick="return check()" 和 onclick="check()" 區別
- C++中break和continue的用法和區別C++
- break,continue,return區別
- C#中continue、return、break的區別及作用C#
- 'return await promise' 與 'return promise' 這細微的區別AIPromise
- C++中L和_T()之區別C++
- preventDefault()與return false區別False
- C和C++區別C++
- c++中指標和引用的區別?C++指標
- JavaScript--分支+迴圈(continue、break、return的區別)JavaScript
- 關於java的引用和c++的區別JavaC++
- JavaScript中for in 和for of的區別JavaScript
- Js中for in 和for of的區別JS
- mysql中!=和is not的區別MySql
- Python中is和==的區別Python
- JavaScript中==和===的區別JavaScript
- Linux中“>”和“>>”的區別Linux
- Python 中 is 和 == 的區別Python
- mysql中“ ‘ “和 “ ` “的區別MySql
- 好程式設計師Python培訓分享print和return的作用及區別程式設計師Python
- PHP 中的 -> 和 :: 的區別PHP
- C++基礎(八)struct和class的區別C++Struct
- C/C++引用和指標的聯絡和區別C++指標
- java 中equals和==的區別Java
- SQL中where和on的區別SQL
- deferred中done和then的區別
- JS中的!=、== 、!==、=== 的用法和區別JS
- c與c++的區別C++
- c++ 和 c 三目運算子區別C++