21

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

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

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

4

11 に答える 11

18

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

メモリ アナライザーの単純な実装の多くは、実際にはそうではない場合でも、失われたメモリをリークとしてフラグ付けします。

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

ところで、私は決して IBM と提携していません。私はピュリファイを広範囲に使用したばかりで、その有効性を保証します.

編集: これは、メモリ監視に関する優れた入門記事です。これは Purify 固有のものですが、メモリ エラーの種類に関する議論は非常に興味深いものです。

HTH。

乾杯、

ロブ

于 2008-10-24T12:32:31.237 に答える
12

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

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

このメトリックでゼロを達成するのが難しすぎることはめったにありません。これは、失われたブロックではなく、忍び寄るメモリ使用量を観察することと同じです。キャッシュやUIファニチャーなど、非常に面倒なライブラリが1つあったので、テストスイートを3回実行し、3ブロックの倍数で発生しなかった「リーク」を無視しました。私はまだすべてまたはほとんどすべての実際のリークをキャッチし、邪魔にならない果物を手に入れたら、トリッキーなレポートを分析しました。もちろん、この目的でテストスイートを使用することの弱点は、(1)新しいプロセスを必要としない部分のみを使用できること、および(2)検出されたリークのほとんどがテストコードの障害であるということです。 、ライブラリコードではありません...

于 2008-10-24T12:46:33.953 に答える
11

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

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

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

編集

私は同意します-多くのツールが誤検知を提供する可能性があります。

于 2008-10-24T14:15:03.480 に答える
9

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

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

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

(平均セッション長)*(リークされたバイト数/分) > 0.3 * (プロセスが通常占有するメモリ空間)の場合、おそらくメモリ リークを減らすためにさらに努力する必要があります。0.3 を作ったところです。常識を使って、許容できるしきい値を決定してください。

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

于 2008-10-24T12:25:43.590 に答える
8

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

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

したがって、実際の問題は、メモリをリークているかどうかではなく、プログラムの実行時に継続的にメモリをリークしているかどうかです。プログラムをしばらく使用していて、何をしても、増加するのではなく120バイトの損失が続く場合は、すばらしい成果が得られたと思います。進む。

于 2008-10-24T14:05:56.447 に答える
7

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

于 2008-10-24T12:24:38.053 に答える
2

アプリケーションによって異なります。一部のリークは避けられない場合があります (リークと締め切りを見つけるのに必要な時間のため)。アプリケーションが必要なだけ実行でき、その間に大量のメモリを消費しない限り、おそらく問題ありません。

于 2008-10-24T12:19:52.027 に答える
2

SDL 開発者は Valgrind を使用していないように見えますが、私は基本的に、失われた 120 バイトしか気にしません。

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

そうですね、Valgrind では、特にこのような単純なプログラムでは、「まだ到達可能なメモリ」は実際にはメモリ リークではないことがよくあります。SDL_Quit() には基本的に割り当てがないので、"リーク" は SDL_Init() によって一度だけ割り当てられた構造体であることに間違いありません。

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

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

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

于 2009-01-12T03:50:12.367 に答える
1

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

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

于 2008-10-24T12:47:43.093 に答える
1

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

于 2008-10-24T12:56:25.293 に答える
1

特に Linux 上の SDL では、基礎となる X ウィンドウ ライブラリにリークがあるようです。それらについてできることはあまりありません (ライブラリ自体を修正しようとしない限り、おそらく気が弱い人向けではありません)。

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

一般に、サードパーティのライブラリに対してはもう少し寛容になる必要があります。独自のコードでのメモリ リークは絶対に受け入れるべきではありません。また、メモリ リークの存在は、代替のサード パーティ製ライブラリを選択する際の要因となる必要がありますが、無視する以外に選択肢がない場合もあります (ただし、それらを報告することは良い考えかもしれません)。ライブラリメンテナに)。

于 2009-01-22T02:24:51.447 に答える