2013-08-02 61 views
0
int main() 
{ 
    myClass obj; 

    .... /* doing things */ 
    .... 

    delete &obj; /* illegal */ 
} 

讓我們假設myClass是一個適當的C++類,其中包含所有的東西。現在,我知道這是非法的,這個程序會在運行時崩潰。第一件事就是代碼試圖刪除一個堆棧對象,然後在作用域結束後再次刪除堆棧對象。我想知道這個非法操作的內部。即刪除會發生什麼,它會調用析構函數嗎?它可能看起來像你瘋了一樣,但請幫助我理解。非法刪除一個堆棧對象

+4

它將*可能*崩潰,但與不確定的行爲的情況下,它可能會,而另一方面,不死機或崩潰的大部分時間,但並非總是如此,甚至會造成[鼻魔(HTTP:/ /www.catb.org/jargon/html/N/nasal-demons.html)。更重要的是,你的問題沒有辦法說明如何處理,未定義行爲的本質在大多數情況下是不可預測的。 –

+1

通過在非優化版本中檢查生成的代碼,不難發現它實際做了什麼 – sehe

+1

這不是一個騙局。 OP在這裏不是問是否安全,他們知道不是。 – jrok

回答

2

您錯過了一件重要的事情 - 除調用析構函數外,delete將釋放分配給new的內存,並將其返回給堆。在堆棧分配變量上調用free是不安全的。要查看它是否會首先調用析構函數,只需在myClass析構函數內部放置一些cout - 在我的配置中,它會在段錯誤之前調用析構函數。

#include <iostream> 

using namespace std; 

class myClass 
{ 
public: 
    ~myClass(){ cout << "Destructor" << endl; } 

}; 


int main() 
{ 
     myClass A; 
     delete &A; 
     cout << "End of main\n"; 
     return 0; 
} 

MSDN

當刪除被用來解除分配存儲器,用於C++類對象,該對象的存儲器被釋放之前,對象的析構函數被調用(如果對象具有析構函數)。拇指

0

規則:

對於每個new也應該只有一個delete
對於每個new[],應該只有一個delete[]
對於每個malloccalloc,應該只有一個free
對於每個stack allocated對象,不應有任何明確的刪除。

其他任何會導致未定義的行爲


即將刪除發生什麼,會不會調用析構函數?

是的,刪除將首先調用對象析構函數。

6

行爲未定義。發生什麼將取決於類的細節,還有哪些事情正在進行,程序的內存管理器是如何實現的,你使用的是什麼編譯器,你在哪個系統上運行,還有可能是我沒有的其他東西花時間思考。這幾乎就像要求瞭解化學儲罐爆炸時發生的情況。

1

這是未定義的行爲。這種標準,我們所生活和仰望的話,說:

否則,提供給運營商的價值在 標準庫中刪除(無效*)應該由先前返回的值之一 調用標準庫無論是運營商新的(爲size_t)或運營商新的(爲size_t, 常量的std :: nothrow_t &)的

所以它的不確定的行爲,任何事情都可能發生,這將取決於實施被錯誤刪除的對象,編譯器,運氣和其他東西。在內部詢問「發生了什麼」是沒有意義的,因爲任何事情都可能發生。最有可能的,因爲delete運營商假設你正確使用它,你最終會在堆棧中引入一些不可預知的變化,這可能會弄亂任何東西。也許你以前的幀指針被覆蓋,也許一些荒謬的返回值被推到一個函數,也許保存的寄存器被覆蓋,所以嘗試恢復寄存器狀態導致非常非法的情況。無論發生什麼,這是醜陋的。