exit and ~destructor

今天在 c++ programming language 上看到這樣描述

 

If a program is terminated using the standard library function exit() ,  the destructors for constructed static objects are called. However, if the program is terminated using the standard library function abort they are not. Note that this implies that exit() does not terminate a program immediately. Calling exit() in a destructor may cause an infinite recursion.

 

查詢msdn有如下解釋:

The exit and _exit functions terminate the calling process. exit calls, in last-in-first-out (LIFO) order, the functions registered by atexit and _onexit, then flushes all file buffers before terminating the process. _exit terminates the process without processing atexit or _onexit or flushing stream buffers

 

When you call the exit or _exit functions, the destructors for any temporary or automatic objects that exist at the time of the call are not called. An automatic object is an object that is defined in a function where the object is not declared to be static. A temporary object is an object created by the compiler. To destroy an automatic object before calling exit or _exit, explicitly call the destructor for the object, as follows:

 

myObject.myClass::~myClass();

 

網上有對此的討論http://www.programfan.com/club/showtxt.asp?id=288606 ,各執一詞,所用vs版本不同也有不同結果

 

 

用vs2008編寫程序測試

#include"stdlib.h"


class ex
{
public:
 ~ex() {
  exit(1); 
 }  // It may cause overflow;
};

int main()
{
 ex a;
 ex a1;
 exit(2);
}

上邊程序結束時返回值爲2,在exit(1)處設斷點,沒有被執行,可見如上所述 automatic varible‘s destructor 沒有被調用

 

 


class ex
{
public:
 ~ex() {
  exit(1); 
 }  // It may cause overflow;
};

 

static ex a;

static ex a2;

int main()
{
 exit(2);
}

上邊程序結束時返回值爲1,在exit(1)處設斷點,exit(1)被執行兩次,可見如上所述destructors for constructed static objects are called。 但是也沒有stack overflow。

 

有人在連接中分析了在vs2005上產生overflow的原因,可以參考一下

 

 

#include <cstdlib>

class A {
public:
    ~A() {
        exit(1);
    }
};

int main() {
    A a1;        // 運行無錯
    static A a2; // stack overflow
    return 0;
}


分析:
1. 若寫了A a1;這句,則在main函數返回之前,會調用a1的析構函數,於是轉到exit(1);。也就是說,並不會等到main函數返回,整個程序就會結束。於是main函數的返回值就被忽略了。證據:不加A a1;時,整個程序返回零。加了以後整個程序返回1。以下是兩種不同情況下,按F5運行後Debug窗口輸出內容的最後一行。
The program '[7828] 001.exe: Native' has exited with code 0 (0x0).
The program '[6664] 001.exe: Native' has exited with code 1 (0x1).
2. 若寫了static A a2;這句,則在運行的時候出現錯誤:stack overflow。C++標準中規定,exit函數的功能是先釋放各種資源,然後退出。這裏的“各種資源”就包括了全局變量和static變量,所以,exit函數會調用a2的析構函數。當main函數返回之後,程序即將結束,此時會調用a2的析構函數。a2的析構函數會調用exit,exit又會調用a2的析構函數,這樣無限的調用下去,最終導致堆棧溢出。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章