2011-01-28 29 views
1

以下は、プログラム内の新規/削除演算子のパターンです。 Valgrindは記憶は「間違いなく失われている」と述べています。私は漏れがどこにあるのか分からない。私の新しい/削除演算子の使い方に何か問題がありますか?valgrindでメモリリークを検出できない

class Generic 
{ 
     GenericInterface *gInterface; //GenericInterface is abstract class 

     public: 
      Generic() 
      { 
       gInterface = NULL; 
      } 
      ~Generic() 
      { 
       delete gInterface; 
      } 
      void Create() 
      { 
      gInterface = new Specific(); 
      } 
    }; 

    class Specific : public GenericInterface 
    { 
     MyClass* _myClass; 

    public: 
     Specific() 
     { 
     _myClass = new MyClass; 
     } 

     ~Specific() 
     { 
     delete _myClass; 
     } 

    }; 

    int main() 
    { 
     Generic g; 
     g.Create(); 
    } 

valgrindはメモリが失われていると言っています。

==2639== 8 bytes in 1 blocks are definitely lost in loss record 2 of 45 
==2639== at 0x4026351: operator new(unsigned int) (vg_replace_malloc.c:255) 
==2639== by 0x804D77C: Specific::Specific() (Specific.cc:13) 
==2639== by 0x804DAFC: Generic::Create() (Generic.cc:58) 

答えて

11

あなたはrule of threeに従っていません。クラスがクリーンアップする必要のあるリソースを管理している場合は、はデストラクタ、コピーコンストラクタ、およびコピー代入演算子を宣言する必要があります。どちらのクラスも、コピーコンストラクタまたはコピー代入演算子を持っていません。

実際、C++ 0xのunique_ptrのようなスマートなポインタを使用しているに違いありません。 Boost、C++ TR1、およびC++ 0xからのshared_ptr;ブーストのscoped_ptr。この特定の問題を引き起こして

可能性の高い問題は、基本クラスGenericInterfaceデストラクタvirtualを作るのを忘れているということなので、間違ったデストラクタが呼び出されているとあなたが動的にSpecificで作成MyClassオブジェクトが破棄されることはありません。

delete基本クラスのデストラクタがvirtualと宣言されていないと、メモリリークからクラッシュまでの間に悪いことが起こるという意味で、オブジェクトの基本クラスの1つにポインタを介してオブジェクトが渡されると、未定義の動作が発生します。

+0

'Virtual〜GenericInterface()= 0;'を置くと、 '〜GenericInterface()'の未定義参照が'特定の'デストラクタ。 – Meebo

+0

@Meebo:派生クラスのデストラクタが呼び出さなければならないので、純粋ではありません。それを定義する必要があります( 'GenericInterface ::〜GenericInterface(){}')。 –

2

あなたのGenericInterfaceデストラクタはおそらく仮想ではないので、gInterfaceが破壊されたときに、デストラクタGenericInterfaceが呼び出されます。

0

GenericInterfaceクラスで仮想デストラクタを宣言していますか?そうでなければ、Specificクラスのデストラクタは呼び出されないので、 "delete _myClass"行は実行されません。

C++は、あなたの人生をより面白くするもうひとつの方法:)

0

あなたのジェネリッククラスのデストラクタであなたもそれを削除する前にgInterfaceポインタをチェックする必要があります。オブジェクトが破棄される前にCreate()が呼び出されないと、問題が発生します。あなたのC++コンパイラが新しい失敗を投げないならば、他のクラスも同じことをするかもしれません。

関連する問題