2009-03-24 15 views
34

私のC++ main関数では、ヒープメモリ(スタックメモリとは対照的に)を使用する変数へのポインタがある場合など - アプリケーションが終了した後で自動的に割り当てが解除されますか?私はそう思うでしょう。プログラムが途中で終了したときにC++でdeleteを呼び出す理由はありますか?

ヒープ割り当ては、終了時にメモリが自動的に割り当て解除される状況では使用されないと思っても、常に削除することをお勧めしますか?

たとえば、これは何か問題がありますか?

int main(...) 
{ 
    A* a = new A(); 
    a->DoSomething(); 
    delete a; 
    return 0; 
} 

私は場合に多分を考えていた私は、リファクタリング(または他の誰かリファクタリング)そのコードをしてdeleteが本当にneccecaryあるアプリケーション、他の場所でそれを置きます。

Brian R. Bondy(C++での影響を具体的に説明しています)の回答と同様に、Paul Tomblinにはgood answer to a C specific questionもあります。これにはC++デストラクタも含まれています。

+0

上記の重複は約Cであり、C++の問題であるデストラクタに関するいくつかの重要な情報が欠落しています。 –

+0

@Brian、私の答えは、デストラクタにも言及しています(今)。これを削除すべきだという私の気持ちは依然として立っています。 –

+0

デストラクタについてどういう意味が分かりません - 明確にしてください。 –

答えて

61

明示的にdeleteを呼び出すことが重要です。これは、デストラクタ内で実行したいコードがある可能性があるためです。ログファイルにデータを書き込むのと同じように。 OSがあなたのためにあなたのメモリを解放するなら、あなたのデストラクタのコードは実行されません。

ほとんどのオペレーティングシステムは、プログラムの終了時にメモリの割り当てを解除します。しかし、それはあなた自身を割り当てを解除するのが良い習慣であり、上記のOSのように、あなたのデストラクタを呼び出さないでしょう。

一般的にdeleteを呼び出す場合は、常に削除を呼び出す必要があります。そうしないと、プログラムでメモリリークが発生し、新しい割り当てに失敗します。

+9

クラスメンバーは、ソケットや接続など、プログラムの終了時に自動的に消えないものを保持している可能性があることを忘れないでください。メモリだけが漏れているわけではなく、すべての漏れが自動的にクリーンアップされるわけではありません。 –

+0

Tree(特にtrie)とdestructorの内部にメモリを割り当てていれば、私がする必要があるのは 'delete'です。それでも明示的にdeleteを呼び出す必要はありますか?私のためにOSに頼っていますか? –

6

クラスAを破壊しなければならないと考えてください。
adeleteをコールしないと、そのデストラクタは呼び出されません。プロセスがとにかく終わるかどうかは、通常はそれほど重要ではありません。しかし、デストラクタが例えばデータベース内のオブジェクト?キャッシュをログファイルにフラッシュしますか?メモリキャッシュをディスクに書き戻しますか?

オブジェクトを削除するのは「良い習慣」だけではなく、場合によっては必須であることがわかります。

7

削除対象のオブジェクトがOSによって安全に解放できない外部リソースを取得した場合を考えてみます。そのオブジェクトでdeleteを呼び出さないと、実際のリークが発生します。

2

必ず自分で削除してください。 OSはこれを処理しますが、簡単に避けることができるバグを除外します。

21

はい、メモリリーク検出ツールでプログラムを実行すると誤検出を防ぐのに役立ちます。

+1

良いリーク検出ツールの方向性を教えてください。 –

+1

Windowsでは、CompuwareのBoundsCheckerは優れていますが高価です。 Linuxでは、私はValgrindについて良いことを聞いてきましたが、まだ試していません。 – Ferruccio

+2

MSVC++の無料のものはVisual Leak Detector(インターネット検索を実行すると簡単に見つかります) –

3

オブジェクトを明示的に削除するもう1つの理由は、アプリケーションに実際のメモリリークがあると、気にならない「漏れ」を見逃す必要がない場合に、valgrindなどのツールを使用してリークを見つけるのが簡単になります。そうじする。

3

削除する別の理由は、今後使用する可能性がある漏れ検出器からの誤ったアラームを避けることです。誤ったアラームがある場合は、漏れ検出器によって報告された実際のリークに注意を払わない場合があります。リークディテクタが間違ったものに埋め込まれます。

+1

公平であるためには、OPのコードでは、これらは「偽」のアラームではありません;) –

9

はい。

  • 標準では保証 OSはメモリをクリーンアップしません。主流のプラットフォームでこれを期待することはできますが、なぜチャンスをとるのでしょうか?
  • メモリを故意にリークしないと、valgrindなどのツールによって報告されるクラッタを最小限に抑えます。
  • この習慣に入ると、間違いなくこのアプローチを間違いなく適用するのは誰ですか?
  • にオブジェクト破壊が必要です。通常、あなたがしていると仮定します。それはあなたを傷つけることはありません。
+1

ポイント#3が私にとって最も魅力的です。割り当てをいつでも削除するだけで、いつ試してみるのが適切なのかを常に判断するのは難しくありません。私は車の回転信号を使用することを思い出させる - 私はいつも人々がそれを使うのに気をつけた理由を疑問に思った。あなたはそれをまったく考える必要がない癖にする方が良いです。 – tenfour

+0

@tenfour:確かに。あなたの前の車が常に適切であることを示すことができない場合は、旋回していないときには必ず確認することはできません。システム全体が故障します。 –

+0

@LightnessRacesinOrbit: "標準では、OSがメモリをクリーンアップすることは保証されていません。"私はまたあなたの3番目のポイントが好きです。 – Destructor

関連する問題