5

原則として、フリー ストアに割り当てられたオブジェクトのみがメモリ リークを引き起こす可能性があります。しかし、スタックで作成されたオブジェクトはそうではありません。

ここで私の疑問は、

int main()
    {
      myclass x;

      ...

      throw;

      ...
    }

throw が処理されない場合は、terminate() が呼び出され、次に abort() が呼び出されてアプリケーションがクラッシュします。このとき、スタック内のオブジェクトは破棄されません (デストラクタは呼び出されません)。

私の理解では、「アプリケーションが(中止または通常の終了によって)終了すると、アプリケーションに割り当てられたすべてのメモリが解放されます」。したがって、これはメモリ リークとは見なされません。

私は正しいですか?

4

7 に答える 7

5

ホストされた環境(たとえば、通常のUnix / Windows / Mac OS X、さらにはDOS、マシン)では、アプリケーションが終了すると、占有していたすべてのメモリがオペレーティングシステムによって自動的に再利用されます。したがって、このようなメモリリークについて心配することは意味がありません。

場合によっては、アプリケーションが終了する前に、 valgrindなどのリークディテクタを介して潜在的なメモリリークを検出するために、割り当てたすべての動的メモリを解放したい場合があります。ただし、そのような場合でも、説明する例はメモリリークとは見なされません。

一般に、デストラクタを呼び出さないことは、メモリリークを引き起こすことと同じではありません。メモリリークは、ヒープに割り当てられたメモリに起因します(新規またはmallocまたはコンテナアロケータを使用)。スタックが巻き戻されると、スタックに割り当てられたメモリが自動的に再利用されます。ただし、オブジェクトが他のリソース(ファイルやウィンドウハンドルなど)を保持している場合、そのデストラクタを呼び出さないと、リソースリークが呼び出されます。これも問題になる可能性があります。繰り返しになりますが、最新のOSは、アプリケーションが終了したときにリソースを再利用します。

于 2010-08-25T21:06:46.620 に答える
4

編集: GMan で言及されているように、「スロー;」以前にスローされた例外を再スローするか、例外がない場合はすぐに終了します。この場合は何もないので、即時終了が結果です。

プロセスを終了すると、最新の OS で残っているユーザーランド メモリが常にクリーンアップされるため、通常は「メモリ リーク」とは見なされません。これは、実行中のプロセスで割り当てが解除されていない参照されていないメモリとして定義されます。ただし、そのようなことを「メモリリーク」と見なすかどうかは、OS 次第です。

于 2010-08-25T20:59:30.047 に答える
2

答えは、OS に依存するということです。このようにしない現代のOSは考えられません。しかし、古いシステム (Windows では 3.1 が勝つと思いますが、いくつかの古い組み込み Linux プラットフォーム) は、プログラムがメモリ要求を解放せずに閉じた場合、OS は再起動するまでそれらを保持します。

于 2010-08-25T20:58:56.777 に答える
1

OPから、

throw が処理されない場合は、terminate() を呼び出します。これにより、abort() が呼び出され、アプリケーションがクラッシュします。このとき、スタック内のオブジェクトは破棄されません (デストラクタは呼び出されません)。

これは実装定義の動作です。

$15.3/9-「一致するハンドラーがプログラム内に見つからない場合、関数 terminate() が呼び出されます。この terminate() 呼び出しの前にスタックがアンワインドされるかどうかは実装定義 (15.5.1) です。」

したがって、これがメモリリークを構成するかどうかも実装定義の動作だと思います。

于 2010-08-26T02:25:25.543 に答える
1

本当の問題は、「myclass は、解放/削除する必要があるメモリ自体を割り当てますか?」ということです。

そうでない場合 (使用するメモリが内部メンバーのみの場合)、スタック上に完全に存在します。その関数を離れると (ただしそうします)、スタック上のメモリは回収され、再利用されます。 myclassなくなっている。それがスタックの仕組みです。

myclass がその dtor で解放する必要があるメモリを割り当てても、throw 中にスタックが巻き戻されるときに dtor が呼び出されるので、まだ運がいいです。dtor は、例外が未処理であると宣言されて終了が呼び出される前に、既に呼び出されています。

問題が発生する唯一の場所は、myclass に dtor があり、dtor が独自の例外としてスローする場合です。最初のスローからのスタックのアンワインド中に発生する 2 番目のスローでは、それ以上の dtor が呼び出されることなく、すぐに終了が呼び出されます。

于 2010-08-25T21:10:01.363 に答える
1

メモリ リークは問題と見なされます。これは、アプリケーションを長時間実行するとシステム メモリが徐々に不足し、最悪の場合、メモリ不足のためにマシン全体が使用できなくなる可能性があるためです。あなたの場合、アプリケーションが終了し、アプリケーションに割り当てられたすべてのメモリがシステムに返されるため、ほとんど問題はありません。

于 2010-08-25T20:59:56.387 に答える
0

私の理解では、「アプリケーションが(中止または通常の終了によって)終了すると、アプリケーションに割り当てられたすべてのメモリが解放されます」。したがって、これはメモリ リークとは見なされません。

私は正しいですか?

メモリ リークはプログラミング エラーの一種であり、キャッチされない例外と比較して、プログラミング エラーの規模がやや低くなります。

IOW、プログラムが適切に終了しない場合、つまりクラッシュした場合、メモリ リークについて話すのは時期尚早です。

他のメモとして、私が過去 10 年間使用してきたほとんどのメモリ アナライザーは、この場合、メモリ リーク アラームをトリガーしません。最初にプログラムがクラッシュしないようにする必要があり、それからメモリ リークをデバッグする必要があります。

于 2010-08-25T21:30:13.977 に答える