2010-11-30 8 views
1

私のC++はこの結果、メモリリークが発生しますか?

#include "stdafx.h" 
#include "stdlib.h" 

class a 
{ 
public: 
    void call() { printf("CALL called\n"); } 
}; 

class b 
{ 
public: 
    b() { this->pointer = new a; } 
    void call() { this->pointer->call(); } 
private: 
    a* pointer; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    b t; 
    t.call(); 

    system("PAUSE"); 
    return 0; 
} 

は、メモリリークのものとなります。..今、私は私が「レベルアップ」-againになった趣味のプロジェクトのためにそれを使用し始めていることはかなり錆びているのですか?プログラムがもうポインタを必要としないと判断した場合、ポインタを削除するにはどうすればいいですか?

"tを削除"すれば十分ですか、あまりにもメモリリークが発生しますか?

答えて

6

pointerbは割り当てられますが削除されることはありません。

すべての新しいのために
b::~b() 
{ 
    delete pointer; 
} 
+3

これでは不十分です。明らかに建設/破壊とRAWポインターに関する経験がない人に助言を与えると、自分自身にとって危険にならないようにしてください。この状況では、最小値には、コピーコンストラクタと代入演算子の無効化も含まれている必要があります(または、それらを正しく定義する方法を説明してください)。 –

2
~b() { delete pointer; } 

、存在する必要があります:あなたはbたびは、スコープの外に出るpointerで指さそうでなければ、aをリークします、aを削除bのデストラクタを定義することをお勧めします一致する削除。

+0

(Typo:彼は "ポインタを削除する"という意味です) – Marvo

+0

(修正しました...) – marcog

+0

おっと、ありがとうございました。 –

1

はい、そうです。

あなたのbクラスにこの機能を追加する必要があります:

~b() { delete this->pointer; }
2

クラスbはあなたが割り当て決してフリーポインタが含まれています。はい、メモリリークが発生します。

これを処理する旧式の方法は、デストラクタでbのポインタを削除することです。これは、再び使用できないことがわかっているからです。

もっと新しい方法は、オブジェクトへの単純なポインタではなく、boost :: shared_ptr(または必要ならばstd :: auto_ptr)のような "スマートポインタ"を使うことです。

1

その他の回答はすべて、pointerメンバーを削除するデストラクタを追加する必要があります。また、そのポインタを適切に扱うコピーコンストラクタとコピー代入演算子(Rule of Three)が必要になることを追加します。

また、boost::shared_ptr(C++ 0xではstd :: shared_ptrになります)などのスマートポインタを調べることをお勧めします。

1

1)はい、aが動的に割り当てられていて解放されないため、メモリリークが発生します。
2)No - delete tは、tがそれ自身のリソースを管理/解放する責任があるため、十分ではありません。
はあなたにもこれがあることを保証します
すなわち

virtual ~b() 
{ 
    delete pointer; 
} 

仮想デストラクタを作ることができるしかし、超安全であるとb すなわち

~b() 
{ 
    delete pointer; 
} 

のためのデストラクタを記述する必要がこれを修正するには派生クラスで正しいデストラクタが呼び出されます。
HTH

1

ポインタを削除することはできません。必要に応じて早期にポインタを削除する "release"というメソッドがあります。この例では、aはbの「pImpl」のように少し見える。すなわち、bで同じ呼び出しを実装するために使用される。

他の回答者が正しく述べたように、bがwith newへのポインタを作成した場合、そのデストラクタはそれを削除する必要がありますが、それ以上のものが必要です。ポインタを削除しようとするbのコピーを作成しないようにする必要があります。したがって、bはコピー不可能であり、割り当て不可能であること。コピー可能または割り当て可能な場合は、ポインターを管理するためにオーバーロードする必要があります。

0

技術的には、一時停止が完了した後にプログラムが終了するため、メモリリークは発生しません。プログラムが終了すると、プログラムによって割り当てられたすべてのメモリが解放されます。

もちろん、他の回答は正しいです。 "b"には、 "new"によって割り当てられたメモリを削除するデストラクタが必要です。

0

上記のクラス "b"には、コンストラクタに割り当てられたメモリを削除するデストラクタが必要です。しかし、マーティン・ヨークが上記でコメントしたように、これは包括的な答えではありません。彼が指摘したように、ここではコピーコンストラクタと代入演算子について注意する必要がある問題がありますが、さらに進んでいきます:生ポインタの使用をやめ、スマートポインタBoostをすぐに使用し始めます。

class b 
{ 
public: 
    b() { this->pointer.reset(new a); } 
    void call() { this->pointer->call(); } 
private: 
    boost::shared_ptr<a> pointer; 
}; 

注二つのこと:ブースト:: shared_ptrの<>を使用するようにリライト

クラス "b" は

  1. 我々はshared_ptrが自動的に破壊するよう明示的なデストラクタを記述する必要はありませんそれが指しているオブジェクト(条件の詳細については、そのドキュメントを参照してください)。
  2. pointerが指すオブジェクトのシャローコピーで十分である場合は、shared_ptrは自動的に独自の「シャローコピー」コピーコンストラクタと代入演算子を提供するため、明示的なコピーコンストラクタまたは代入演算子を記述する必要はありません。

今後のC++ 0x規格には、shared_ptrを含むいくつかのスマートポインタもあります。ブースト中のscoped_ptrおよびshared_arrayおよびscoped_arrayも参照してください。最後に、私はWin32のようなC APIを扱うときに特に役に立ちます。

0

クラスBでは、単にスタックにAインスタンスを作成できます。これはオーナーシップの問題を軽減します。私の経験では、スタック上にメンバ変数を作成することができます。削除は自動的に行われます。あなたができない場合は、サードパーティがあなたのBクラスへのポインタを提供することを提案します。指定されたポインタは、ある種のスマートポインタ内にカプセル化されています。

C++の「問題」の1つは所有権です。私。誰が何を所有し、誰が何を削除すべきか慎重なクラス設計だけでこの問題を緩和し、メモリリークを減らすことができます。

あなたのやや工夫した例では、クラスBはコンストラクタで作成されたとおり、Aへのポインタを所有しています。したがって、この例では、クラスBにはAインスタンスを削除するデストラクタが含まれている必要があります。

関連する問題