2011-06-20 4 views
0

C++コードのメモリ管理に関する一般的な質問があります。コンパイラは、オブジェクトへのポインタを、スタック上で動的に初期化したオブジェクトへの新しいポインタで置き換えると、潜在的なメモリリークがあると訴える。例:私はその後、ポインタC++のポインタとスタックのメモリ管理

int i = 1; int* c = &i; foo(c);

の状態を変更するには、この機能を使用

int* foo(int* h){ 
int* b = new int(5); 
b = h; //Memory leak here. How do I delete b without creating a dangling pointer? 
return b; 
} 

は、だから私の質問は、私は上記のものと同様の機能を持つクラスを持っています。 foo関数からbをいつ削除できますか?

delete b; 

このデストラクタに行くだろう(私は時間の関数fooの負荷を使用していて、私を助けないであろう。ヒープはおそらくアップ慣れるでしょうので......?)

もしI上記の十分な情報を提供していません。私にお知らせください。

+2

を明確にすべき基本から始めレッツ:あなたの関数 'foo'は値がまったくそのパラメータによって指さ変更されません。正確に何をすべきか? – Jon

+0

'foo(c);'は 'c 'と何もしません – rmflow

+0

あなたの質問を理解できませんでした。しかし、メモリリークの危険性があります。例えば:foo(new int);ここでintは、fooを呼び出すときにリークされます –

答えて

2

これは一般的な質問ですので、自分のクラス内でRAIIを使用して処理されたスマートポインタを使用するのが一般的な方法です。

スマートポインタは、生ポインタをカプセル化し、必要なメモリ管理を処理します。クラスが破棄されると、その時点で保持されているポインタ値が手動で削除されることなくクリーンアップされます。スマートポインタに新しい値を割り当てると、既存の値があれば自動的に削除されます。

boost::scoped_ptrここであなたのためにうまくいくはずです。

スタック上のものとヒープ上のものについては、ここでも混乱しているようです。あなたはfooを何度も呼び出しているのでスタックを使い果たしません(fooに無限に戻る場合を除き、最終的にスタックスペースが足りなくなる場合を除きます)。ローカル変数bがスタックにありますが、ヒープ上でnewを使用して割り当てられたメモリを指しています。 fooを終了すると、スタックは呼び出し関数用にリセットされます。bで使用されるスタックメモリは、呼び出される次の関数で使用できるようになりますが、bが指し示すヒープメモリの所有権を保持する必要があります。

EDIT:いくつかのサンプルコードは、スマートポインタのアプローチに

class MyClass { 
public: 
    MyClass() {} // no explicit init for myPointer needed 
    ~MyClass() {} // frees up any pointer held in myPointer, no explicit delete needed 

    void Foo(int* c) 
    { 
    myPointer.reset(c); // releases any existing value, takes ownership of c 
    } 

private: 
    boost::scoped_ptr<int> myPointer; // initially empty 
}; 
+0

こんにちはスティーブ。最後の段落は、私が求めている質問です。それを上手く策定したことはありません。どのように私はヒープからメモリを解放するつもりは、Cがぶら下がりポインタになることなく行くだろうか?またはこれは起こりませんか?再度、感謝します! – MWright

+0

明確にするためにいくつかのコードを追加しました。スマートポインタとRAIIは、C++の生産性とコード品質を向上させる重要な要素です。カバーの下で何が起こっているのかを理解することが重要です。もちろん、元の質問のように 'new/delete'を使って手動で行う方法もあります。 –

+0

ありがとうsteveこれは素晴らしいです! STLの一部を強化するか、ライブラリが必要ですか?これは非常にC#ish – MWright

3

あなたが本当に機能に割り当てられた新しいポインタとポインタの値を交換したい場合は、私は参照を使用することをお勧めします:もちろん

void SomeClass::foo(int*& h) 
{ 
    delete h; 
    h = new int(5); 
} 

を、これはあなたがへのポインタでそれを呼び出す場合は解除されますintではなく、ヒープ上にがありますので、その場合はdeleteできません。そうしないでください。

+0

こんにちは。上記の機能を変更しましたか?削除bはどこに行きますか?関数にhを設定した後、またはhがぶら下がりポインタになるでしょうか? – MWright