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のインスタンスが2つあります。ありがとうございます。 – Zefick

+0

私は仮想デストラクタの使い方についてもっと読んでいます。 –

答えて

3

これは未定義の動作です。あなたが見たのと同じように、状況によってはうまくいくように見えるかもしれませんが、状況によってはそうではありません。

は、少なくとも基底クラスは、c3(又はc1c2仮想デストラクタを持たなければなりません。例えば第一の代替(削除対象)において

(強調鉱山)

、 オブジェクトの静的な型を削除する場合:標準、$5.3.5/3 Delete [expr.delete]によれば

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

動的タイプと異なる場合、タイプ は、オブジェクトの動的タイプの基本クラスであり、 が削除され、静的型は仮想デストラクタを持たなければならないか、 の振る舞いは定義されていません

2

newによって返されなかったポインタを削除しようとしています。ソリューションの場合は、基底クラスの場合はvirtual destructorです。基本クラスへのポインタを使用してオブジェクトを削除する場合、基本クラスにはvirtualデストラクタが必要です。

1

前の回答に追加するには、undefined行動は(あなたの例ではほとんどの時間を、ではなく)基本クラス手段へのポインタをキャストしているという事実から来ているをスライス:ポインタが調整されている(つまり、インクリメント)を使用して、埋め込みクラスの先頭を指すようにします。

ポインタがインクリメントされたときにdeleteを呼び出すと、メモリの一部が解放され、その一部にがダブリングする恐れがあります。

関連する問題