3
#include <iostream> 
using namespace std; 
class c1 {}; 
class c2 : public c1 {}; 
class c3 : public c1 {}; 
class c4 : public c2, public c3 {}; 

int main() { 
    c4 *x1 = new c4; 
    c3 *x2 = x1; 
    delete x2; // segmentation fault 
} 

嗨,我想了解類型轉換和繼承,我發現這個問題。我有一個指向最派生的類,並指定(隱式)中間任何類,同時刪除,我認爲它應該能夠刪除第一個新分配的空間。在一些編譯器中,它看起來很好,但在linux gcc 4.7.2版(Debian 4.7.2-5)中,它給出了分段錯誤。無法弄清楚,爲什麼?任何幫助/指針/建議將不勝感激。分段錯誤刪除指針

注 - 類是以鑽石問題的形式派生的。

+1

你應該在c3中實現虛擬析構函數。 – Zefick

+0

這不是鑽石問題,因爲沒有虛擬繼承。 c4類實際上有兩個c1實例。 – Zefick

+0

謝謝。我正在閱讀更多關於虛擬析構函數的用法。 –

回答

3

這是未定義的行爲。正如你所看到的,在某些情況下它可能看起來很好,在某些情況下它不會。

至少基類c3(或c1c2)應具有虛擬析構函數。例如

class c3 : public c1 { 
public: 
    virtual ~c3() {} 
}; 

根據標準,$5.3.5/3 Delete [expr.delete]

(重點煤礦)

在第一種方式(刪除對象),如果 對象的靜態類型要被刪除不同於它的動態類型,靜態的 類型應該是動態類型的對象的基類,將 刪除,靜態類型應該具有虛擬析構函數或 行爲未定義

2

試圖刪除未由new返回的指針。對於基礎類的解決方案使用virtual destructor。當通過指向基類的指針刪除對象時,基類需要一個virtual析構函數。

1

要添加到以前的答案,在undefined行爲來自於一個事實,即鑄造的指針指向一個基類機構(大部分的時間,而不是在你的例子)切片:指針被調整(即遞增)指向嵌入類的開始。

因此,在增加的指針上調用delete時,可能會釋放部分內存,並讓其中的一部分懸空