2009-09-04 43 views
1

私はカスタムのtextfile-data parser(JSON風)を書いていますが、小さなメモリリークを見つけようと多くの時間を浪費しています。C++:std :: mapを使った小さなメモリリーク

私はVC++ 2008とコマンド_CrtMemCheckpointと_CrtDumpMemoryLeaksを使用してメモリリークをチェックしています。私は「問題を狭めるために管理している

{290} normal block at 0x00486AF0, 16 bytes long. 
Data: < H `aH hH eH > C0 9A 48 00 60 61 48 00 18 68 48 00 D8 65 48 00 

:私は任意のファイルを解析し、(主張任意の他のメモリと一緒に)メモリから削除する場合

は、私はこのようになります16バイトのメモリリークを取得しますこれまでのコードの「行:

classDefinitions[FastStr(cString)] = classDef; 

classDefinitionsstd::map<FastStr, FSLClassDefinition*>で、私のパーサクラスのプライベートメンバーです。

FastStrは単純なC文字列をキー値として使用するための単純なchar * "ラッパー"です。メモリリークはありません(新しいコマンドはありません)。 'FSLClassDefinition *'は明らかに単純なクラスポインタなので、そこには何も変わっていません。

今ここでキャッチです:

  1. この行は、構文解析処理中に何度も実行されますが、私は1つの16バイトのブロックがリークします。
  2. 別のファイルを解析すると、別の16バイトのメモリリークはありません
  3. ({}コードブロック内にある)パーサーをメモリから削除した場合は、別のコードブロックで再作成し、別のファイルを解析すると、が返されます。 16MBのメモリリークが発生します。

これは私には、std :: mapにメモリリークがあると思われます。しかし、それは私の間違いかもしれません...私はそれがの前に、それがの前に解析を停止するので、それが違反行だと確信しています。そこにのメモリリークの場合は、この行の後にの後に解析を停止すると、ちょうどになります。

誰でもコメントできますか?

+4

有名な最後の言葉:FastStr:「メモリリークはありません」 –

+0

std :: mapにメモリリークがあるとは思えません(テストされていない一部の曖昧なベンダーのSTLバージョンを使用している場合を除きます)。何百万人ものC++ユーザー)。 –

+0

ヨーク:あなたのコメントは本当に私の一日を作りました:-)しかし、真実は、結局、メモリリークはありませんでした。 –

答えて

10

リークレポートの "{290}"は、リークされたメモリブロックのメモリ割り当てのシーケンス番号です。このシーケンス番号が常に同じ場合、_crtBreakAllocを使用して、その割り振り順序番号がヒットしたときにデバッガーを中断させることができます。スタックトレースから、このブロックがどこに割り当てられているかを知ることができます。どこで、どのような目的のために割り当てられているのか分かると、割り当てが解除されていない理由を判断するのがかなり簡単になりがちです。

_crtBreakAllocについては、デバッグヒープのドキュメントを参照してください。

4

ちょっとしたことがあります:std::mapにはリークはありません。このコードは、すべての開発者が見るためのものであり、今までには捕らえられていました。

正しい場合は、classDefまたは匿名のFastStrオブジェクトがリークしていると思います。しかし、両方のコードがなければ、それを伝えるのは難しいです。あなたはそれらが両方の指針であると言います。問題の行は実際の問題ではなく単に症状に過ぎないと私は信じています。コードを表示するのはどうですか?

+2

合理的ではないと主張しましたが、問題の原因となるものの適切な組み合わせを見つけた可能性があるため、実際に地図が漏れていないかどうかは確信できません。ツールには時にはバグもあります。 –

+1

ツールには時折バグがあります。しかし、これは私たちが話しているSTLです。それはずっとずっとずっとずっと多くのC++プログラマーによって使用されています。この大きさのバグは、マップが本当にスリムなような共通のコンテナに存在する可能性があります。あまりにもスリムです。 –

+1

STLは永遠に残っていますが、この実装にはありません。それは半新製品ですが、あなたは何が変わったのか分かりません。再び、私はそれがSTLの問題だと真剣に疑うが、これらは起こる。 –

2

メモリ「リーク」は繰り返し使用すると縮尺が変わらないため、おそらくリークではありませんが、ライブラリによって割り当てられ、メモリプロファイリングが完了するまで解放されないメモリです。メモリはしばしばライブラリによって割り当てられ、その後の呼び出しで再利用されます。ライブラリはあなたの呼び出しのうち最後の呼び出しを知ることができないので、プログラムが終了するまで解放されません。

+0

これはどのライブラリですか?標準ライブラリは確かにそれをしません。マップはデストラクタが呼び出されるとすぐにそのメモリのすべてを解放します。 – jalf

+0

Motif、Qt、X11など...少しのメモリを犠牲にして速度を最適化するのが一般的な方法です。 – Bill

1

これは、FastStrを見ることになります。あなたはそれが単純なchar *ラッパーだと言いますが、それはどのようにコピーされて処理されますか?内部char *がコピーまたは再作成されていますか?) FastStrのコードをお願いしますか?

あなたの証拠にはいくつかの静的なデータが含まれているか、「パーサー」があなたのテストコードブロックに作成されているだけであれば、「パーサ」オブジェクトのメンバがメモリリークの発生源です。

もう1つの提案は、valgrindなどのよりわかりやすいツールの下でコードを実行してリークを突き止めることです。 Valgrind(またはPurify)は、コード内のメモリリークの正確な場所を示します。

+0

ソースコードを表示したくない(8KB)と読者を混乱させる恐れがあります。 'new'演算子はありません。コピーされると、新しいFastStrは元のポインタをchar *にコピーします。私はダブルとトリプルをチェックしました。さらに、FastStrのインスタンスは、サイズが16バイトではなく、20バイトです... –

+0

しかし、あなたがそれを一見することを主張すれば、私はそれを投稿します。 –

+0

それでは、FastStrはchar *を内部的に整理していますか?私はそれを削除しないと仮定し、まだメモリはどこかに割り当てられている必要があります... * FastStrがヒープまたはスタックをラップしたchar *ですか? –

2

これまでのところ、私たちはあなたのコードの一行を見ていないので、私たちはすべての広く使用されているSTLの実装では、」それよりもはるかに多くを言うことのためにそれはかなり不可能だ、std::mapの下、ないリークメモリを行いますいかなる状況でも。マップのデストラクタが実行されると、すべてのメモリが解放されたです。

もちろん、わかりにくい独自のSTL実装を使用している場合、すべてのベットはオフですが、それ以外の場合はマップが原因ではありません。

もちろん、mapのメモリが漏れていると思われる場合は、それを実行してください。ヘッダーのみのコードなので、表示され、自分のコードと同じようにデバッグできます。デバッガでそれをステップ実行し、どの割り当てが行われたか、そしてそれらが再び解放されるかどうかを確認します。

しかし、おそらく、問題はFastStrか、あなたのコード内にあるものです。

エラーを再現する可能な限り最小限の例を得るために、できるだけコードから切り離してください。

最初からフルプログラムを実行しないでください。あなたが投稿した行に問題があると確信できるならば、多くの可能性を排除する最初の解析をすべてスキップすることができます。同様に、その後に起こることもすべて削除します。それでエラーが再現されない場合、問題はあなたが孤立した行にはありません。

エラーを再現した小さなサンプルを取得した場合は、ここに投稿して覗いてみることもできます。

0

"valgrind --leak-check"を使ってこのコードをLinuxで実行することはできますか?もしそうなら、valgrindはメモリが漏れていることを示すことができます。

4

OldFartが問題の究極の解決策を提供しました。

最初にメモリリークはありませんでした。それだけでVC++ 2008デバッガ熱心されていた、

return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty))); 

しかし、彼らは真のメモリリークはありませんでした:デバッガによって提案されたメモリ位置は、STLにxmemoryファイル、ライン ました。私はPurifyPlus(eval.version)でテストし、プログラムにメモリリークがないことを示唆しています。したがって、16バイトはプログラムの終了時に削除されますが、STLが先にそれをしないことはあまり良くありません。

あなたの返信にも感謝しています。最初は問題はありませんでした。

2

DLL内のファイルスコープにマップを配置すると、MS Visual Studio 2008はメモリリークを起こします。あなたがマップで何もする必要はありません、それを宣言します。

ポンドが含まstd名前空間を使用して<マップ>

map < short、long > test_map;

...

検出されたメモリリーク! オブジェクトをダンプする - > {143}通常ブロック、0x00037140、24バイト。 データ:< @q @q @q> 40 71 03 00 40 71 03 00 40 71 03 00 CD CD CD CD オブジェクトのダンプ完了。

メインプログラムでは発生しません。マップが関数スコープ内にある場合は発生しません。恐らくスプリアスなのです。メモリリーク検出が停止した後、マップの割り当てが解除されます。

2

DLL内のファイルスコープにある静的マップが(MS Visual Studio 2008を使用して)同じ小さなメモリリーク状況を生成することを確認するだけです。

関連する問題