質問

私は C++ で SDL の実験を始めたばかりですが、メモリ リークを定期的にチェックすることは早い段階で身につける良い習慣になるかもしれないと思いました。

これを念頭に置いて、私はリークを見つけるために Valgrind を介して「Hello world」プログラムを実行してきましたが、最も基本的なもの以外はすべて削除しました。 SDL_Init() そして SDL_Quit() ステートメントでは、Valgrind は依然として 120 バイトが失われ、77k がまだ到達可能であると報告しています。

私の質問は次のとおりです。メモリ リークの許容制限はありますか、それともすべてのコードを完全にリークしないように努めるべきでしょうか?

役に立ちましたか?

解決

Valgrind の測定で誤検知が検出されないように注意してください。

メモリ アナライザの単純な実装の多くは、実際にはリークではないにもかかわらず、失われたメモリをリークとしてフラグを立てます。

おそらく、外部リンクセクションにある論文のいくつかを読んでください。 Purify に関するウィキペディアの記事. 。Purify に付属のドキュメントでは、メモリ リークを検出しようとすると誤検知が発生するいくつかのシナリオが説明されており、さらに Purify が問題を回避するために使用する手法についても説明されています。

ところで、私はIBMとは一切関係がありません。私は Purify を広範囲に使用しており、その有効性を保証します。

編集:ここにあります 素晴らしい紹介記事 メモリ監視についても説明します。Purify に特有のものですが、メモリ エラーの種類に関する議論は非常に興味深いです。

HTH。

乾杯、

ロブ

他のヒント

「メモリリーク」の定義には注意する必要があります。初回使用時に一度割り当てられ、プログラム終了時に解放されるものは、リーク検出器によって表示されることがあります。これは、初回使用前にカウントを開始するためです。しかし、これはリークではありません(何らかのグローバルな可能性があるため、デザインが悪いかもしれませんが)。

特定のコードチャンクがリークするかどうかを確認するには、合理的に1回実行し、リークディテクタをクリアしてから再度実行します(もちろん、リークディテクタのプログラムによる制御が必要です)。 「漏洩」するもの通常、プログラムの実行ごとに1回は重要ではありません。 「漏洩」するもの通常、実行されるたびに最終的に問題になります。

このメトリックでゼロに達するのが難しいことはめったにありません。これは、ブロックが失われるのではなく、メモリ使用量の増加を観察するのと同じです。キャッシュとUI家具などで非常に手間がかかるライブラリが1つあったので、テストスイートを3回実行しただけで、「リーク」を無視しました。 3ブロックの倍数では発生しませんでした。私はまだ本当の漏れのすべてまたはほとんどすべてを捕らえ、そして控えめな果物が邪魔にならないようになったらトリッキーなレポートを分析しました。もちろん、この目的でテストスイートを使用する場合の弱点は、(1)新しいプロセスを必要としない部分のみを使用できること、および(2)発見したリークのほとんどがテストコードの欠陥であるということです。 、ライブラリコードではありません...

メモリリーク(およびその他の不注意な問題)を伴う生活は、最高の状態では(私の意見では)非常に悪いプログラミングです。最悪の場合、ソフトウェアが使用できなくなります。

最初にそれらを導入することは避け、あなたと他の人がそれらを検出しようとするツールを実行する必要があります。

ずさんなプログラミングを避けてください-すでに十分な数の悪いプログラマーがいます-世界は別のものを必要としません。

編集

同意します-多くのツールが誤検知を提供できます。

メモリ リークが本当に心配な場合は、いくつかの計算を行う必要があります。

アプリケーションを 1 時間ほどテストしてから、リークしたメモリを計算する必要があります。このようにして、リークしたメモリ バイト/分値を取得します。

ここで、プログラムのセッションの平均時間を見積もる必要があります。たとえば、notepad.exe の場合、15 分が妥当な見積もりの​​ように思えます。

もし (平均セッション長)*(リークしたバイト数/分) > 0.3 * (プロセスが通常占有しているメモリ領域), 場合は、メモリ リークを減らすためにさらに努力する必要があるでしょう。私は 0.3 をでっち上げただけです。常識に従って、許容可能なしきい値を決定してください。

プログラマーであることの重要な側面はソフトウェア エンジニアであることであることを忘れないでください。エンジニアリングとは、2 つ以上の悪い選択肢から最も最悪でない選択肢を選択することであることがよくあります。オプションが実際にどれだけ悪いかを測定する必要がある場合、数学は常に役に立ちます。

デスクトップアプリケーションの場合、小さなメモリリークは実際の問題ではありません。サービス(サーバー)の場合、メモリリークは許容されません。

ほとんどのOS(Windowsを含む)は、プログラムがアンロードされると、プログラムに割り当てられたすべてのメモリを返します。これには、プログラム自体が追跡できなくなった可能性のあるメモリが含まれます。

それを考えると、私の通常の理論では、起動時にメモリをリークしても問題ありませんが、実行時にメモリをリークしても問題ありません。

つまり、本当に問題は、メモリをリークしている場合ではなく、プログラムの実行中にメモリを継続的にリークしている場合です。しばらくプログラムを使用し、何をするにしても、増加するのではなく120バイトが失われたままであれば、あなたは素晴らしいことをしたと思います。先に進みます。

アプリケーションによって異なります。漏れが発生するのは避けられない場合があります(漏れを見つけるのに必要な時間と締め切りのため)。あなたのアプリケーションがあなたが望む限り実行でき、その時間に狂った量のメモリを消費しない限り、おそらく大丈夫です。

SDL開発者はValgrindを使用していないように見えますが、基本的に失われるのは120バイトだけです。

  

これを念頭に置いて、Valgrindで「Hello world」プログラムを実行してリークをキャッチしました。最も基本的なSDL_Init()およびSDL_Quit()ステートメントを除くすべてを削除しましたが、Valgrindは引き続き120バイトが失われ、77kはまだ到達可能です。

さて、Valgrindでは、「まだ到達可能なメモリ」多くの場合、特にこのような単純なプログラムでは、実際にメモリがリークすることはありません。 SDL_Quit()には基本的に割り当てが存在しないため、「リーク」は安全に賭けることができます。 SDL_Init()によって一度割り当てられた構造です。

有用な作業を追加し、それらの量が増加するかどうかを確認してください。有用な作業のループを作成して(SDL構造の作成や破棄など)、繰り返しの量とともにリークの量が増加するかどうかを確認してください。後者の場合、リークのスタックトレースを確認して修正する必要があります。

それ以外の場合、これらの77kリークは"メモリとしてカウントされ、プログラム終了時に解放する必要がありますが、OSに依存して解放します。

したがって、実際には、これらの120バイトが誤検知ではなく、通常はわずかである場合、私は今、より心配しています。 Valgrindの誤検知は、ほとんどの場合、初期化されていないメモリの使用が意図されている場合です(たとえば、実際にパディングされているため)。

Purifyに関するRob Wellsのコメントに従って、他のツールをダウンロードして試してみてください。私はBoundsCheckerとAQTimeを使用していますが、長年にわたってさまざまな誤検知が見られました。メモリリークはサードパーティのコンポーネントにもある可能性があり、分析から除外することもできます。例から、MFCは最初のビューバージョンで多くのメモリリークがありました。

IMO、メモリリークは、長寿命の可能性があるコードベースに入るコードについて追跡する必要があります。それらを追跡できない場合は、少なくとも同じコードの次のユーザーのために存在することをメモしてください。

最初に発生するメモリリークは、時間の経過とともに大きくなる場合にのみ深刻な問題になります。そうでない場合、アプリは外側から少し大きく見えるだけです(明らかに、ここにも制限があるため、「深刻」です)。 時間の経過とともに増大するリークがある場合、問題が発生している可能性があります。ただし、問題は状況によって異なります。メモリの行き先を知って、そのマシンでプログラムや他のすべてを実行するのに十分なメモリを常に確保できる場合は、多少問題ありません。 ただし、メモリの行き先がわからない場合は、プログラムを出荷せず、掘り続けます。

特にLinux上のSDLでは、基礎となるX Windowsライブラリに何らかの漏れがあるようです。それらについてできることはほとんどありません(ライブラリ自体を修正したい場合を除き、おそらく気弱な人向けではありません)。

valgrindの抑制メカニズム(valgrindのmanページの--suppressionsおよび--gen-suppressionsを参照)を使用して、これらのエラーを気にしないように指示できます。

一般に、サードパーティのライブラリに対してもう少し寛大でなければなりません。独自のコードでメモリリークを絶対に受け入れてはなりません。また、メモリリークの存在は、代替のサードパーティライブラリを選択する際の要因になるはずです。時々、それらを無視する以外に選択肢がない場合がありますライブラリメンテナへ)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top