2009-10-26 69 views
1

我遇到了一個錯誤。當我打電話刪除對象體系頂部的對象(希望能引起它的子對象的刪除),我的編程'退出,我得到這個:關於C++內存分配和刪除的問題

*** glibc detected *** /home/mossen/workspace/abbot/Debug/abbot: double free or corruption (out): 0xb7ec2158 ***

其次是什麼樣子了內存轉儲某種類型的。我已經搜索了這個錯誤,並且從我收集的內容中看到,當您嘗試刪除已被刪除的內存時似乎會發生這種錯誤。不可能,因爲在我的代碼中只有一個地方試圖刪除。這是古怪的部分:它不會在調試模式下發生。有問題的代碼:


Terrain::~Terrain() 
{ 
    if (heightmap != NULL) // 'heightmap' is a Heightmap* 
    { 
     cout << "heightmap& == " << heightmap << endl; 
     delete heightmap; 
    } 
} 

我註釋掉的高度圖析構函數的一切,還是這個錯誤。當發生錯誤時,

heightmap& == 0xb7ec2158

被打印。在調試模式下,我可以慢慢瀏覽代碼,並且

heightmap& == 0x00000000

被打印出來,並且沒有錯誤。如果我註釋掉'刪除高度圖';線,錯誤從未發生。上面的析構函數是從另一個析構函數調用的(單獨的類,沒有虛擬析構函數或類似的東西)。高度圖指針new'd在這樣的方法:


Heightmap* HeightmapLoader::load() // a static method 
{ 
    // .... 
    Heightmap* heightmap = new Heightmap(); 
    // ....other code 
    return heightmap; 
} 

難道是與返回這是一個靜態方法的堆棧空間初始化的指針?我是否正確地進行刪除?有關我可以檢查或做得更好的任何其他提示?

回答

2

如果從不呼叫load()會發生什麼情況?你的類構造函數初始化爲heightmap,還是在它到達析構函數時未初始化?

而且,你說:

...刪除已被刪除的記憶。不可能,因爲在我的代碼中只有一個地方試圖刪除。

但是,你有沒有考慮到你的析構函數可能你的程序的執行過程中被調用一次更多。

+0

是的,就是這樣。我確定heightmap *正在設置中(不是在構造函數中,而是在setter方法中),可惜它不是。謝謝,格雷格! – Mossen 2009-10-26 04:59:47

+1

始終在構建過程中初始化所有指針。空指針可以安全地刪除(無操作)。如果你的構造函數在初始化列表中將指針設置爲0,那麼代碼從一開始就是正確的。 – 2009-10-26 06:43:56

+1

當然,可能會有複製構造和/或分配,使兩個對象指向同一個內存區... – 2009-10-26 08:44:28

1

這很有可能是你打電話給這個dtor兩次;在調試模式下,指針恰好在刪除時歸零,在優化模式下,它是獨立的。雖然不是一個乾淨的解決方案,但想到的第一個解決方法是在刪除後立即設置heightmap = NULL; - 它不應該是必需的,但當您尋找解釋爲什麼要銷燬某些地形實例兩次!)[[在您顯示的少量代碼中絕對沒有任何內容可以幫助我們解釋導致雙重破壞的原因]]

2

在調試模式下,指針通常設置爲NULL和內存塊清零。這就是您在調試/發佈模式下遇到不同行爲的原因。

我會建議你使用,而不是傳統的指針

auto_ptr<Heightmap> HeightmapLoader::load() // a static method 
{ 
    // .... 
    auto_ptr<Heightmap> heightmap(new Heightmap()); 
    // ....other code 
    return heightmap; 
} 

這樣你以後不必刪除它,因爲它會爲你自動完成

也看到boost::shared_ptr智能指針

+0

謝謝,我沒有意識到有關調試模式...我習慣於Java編碼.. 。我會看看auto_ptr! – Mossen 2009-10-26 05:02:06

+0

+1,也可以從boost或std :: tr1中查看'scoped_ptr <>'和'unique_ptr <>'。它們是智能指針內存管理的不同解決方案。 – 2009-10-26 07:03:09

0

它看起來像未經初始化指針的經典案例。正如@Greg所說,如果load()不是從Terrain調用的呢?我想你並沒有在Terrain構造函數中初始化HeightMap*指針。在調試模式下,該指針可能被設置爲NULL,並且C++保證刪除空指針是有效的操作,因此代碼不會崩潰。但是,由於優化,在發佈模式下,指針處於未初始化狀態,並且您嘗試釋放一些隨機內存塊併發生上述崩潰。