2011-07-15 14 views
5

私は2,3日間メモリ問題を追跡しようとしています。私のプログラムは約3GBのメモリを使用しています。約200MB〜300MBを使用する必要があります。 Valgrindは実際にピーク時に〜300MBを使用していると報告しており、メモリリークは報告されていません。巨大メモリの使用量を追跡できません

プログラムは入力ファイルを読み込み、そのファイルにすべてのユニークワードを格納します。それはマルチスレッドであり、私は4つのスレッドを使って実行しています。データの私の主な発生源は、以下のとおりです。言葉と関連する値のリストの間

  • wchar_t型の定数サイズの配列(4MBの合計)
  • 地図。これは入力の大きさとともに増加します。入力ファイルに一意の単語が1,000,000件ある場合、ツリーには1,000,000件のエントリが存在します。

私は膨大な数の割り当てと割り当て解除(新規と削除を使用して) - ユニークワードあたり少なくとも2つを実行しています。私が解放したメモリが何らかの理由で再利用されていない可能性はありますか?プログラムはますます多くのメモリを獲得し続けるでしょうか?それは継続的に実行されると、より一貫してそれをつかむ。

一般的に、私はここからどこに行かなければならないのですか?

編集1(Grahamのアドバイスに基づいて): 割り当てを最小限に抑えることを試みます。私はスレッドごとに1つの文字列(単語がこの文字列よりも長い場合には時々成長するかもしれません)で作業しますが、私のコードを正しく覚えていれば、膨大な数の新規/削除呼び出しがなくなります。すべてがうまくいけば、入力バッファの一回限りの割り当て、スレッドごとの文字列の割り当て(いくつかのrealloc)、マップエントリごとの2つのalloc(キー用と、値用)が残されます。

ありがとうございます!

+0

グラハムの答えが有効であるようです。どのくらいのメモリが使用されているのか、実行中のOS(64ビットまたは32ビット)はどのように決定していますか?データ構造や完全なクラスオブジェクトだけを新規/削除するオブジェクトはありますか? – Foon

+0

私はValgrindとコマンドfree -mを使用しています(どのくらいのメモリが空いているかを報告します。これは64ビットLinux上です。私はstd :: wstringとc-style文字列を使ってこれを試しました。 – lapis

答えて

7

ヒープフラグメンテーションの可能性があります。このような膨大な量の小さなブロックを割り当てたり解放したりしているので、その後の割り当てで再利用するには小さすぎる小さなチャンクがある可能性があります。これらのチャンクは効果的に無駄になるので、プロセスは新しい割り当てを尊重するためにシステムからより多くのメモリを奪い続ける必要があります。

各文字列の十分な大きさのデフォルト容量をstring::reserve()で予約してから、文字列を消去して(削除するのではなく)空の状態にすることで、効果を緩和できます。その後、空の文字列のリストを常に新しいものを割り当てるのではなく、再利用するようにしておきます。

編集:上記の提案は、割り当てられるオブジェクトがstd::stringであることを前提としています。そうでない場合は、古い空のオブジェクトを再利用するための一般的なテクニックを適用することができます。

+0

これは入力のおかげで、この時点で最も可能性の高い問題のように聞こえます!オリジナルの投稿を編集してみてください。 – lapis

0

メモリプログラムの解放は、再度割り当てることができるヒープに返す必要があります。

ただし、オペレーティングシステムに解放されているわけではありません。多くの場合、アプリケーションは割り振られ解放されたメモリを「所有」し続けるでしょう。

これはWindowsアプリですか?どのようにメモリを割り当てて解放していますか?そして、あなたはどのようにアプリケーションが使用しているメモリの量を決定していますか?

+0

彼がValgrindを使っているのなら、それはlinuxです。 –

+0

ええ、gcc 4.4.4を使ってLinuxでビルドされました。私はvalgrindとfree -mで新しい/削除、プロファイリングを使用します – lapis

0

可能であれば、リソース割り当てをクラスにラップしてください。コンストラクタでnewを呼び出し、デストラクタで削除します。スコープを試してみて、メモリ管理がより自動的に行われるようにしてください。

http://en.wikipedia.org/wiki/RAII

関連する問題