2010-12-06 16 views
6

私は大きなモノリシックアプリケーションの特別なビルドを制作しようとしています。私が解決しようとしている問題は、難しい再現性のある膨大なメモリ割り当てを追跡することです(OSレポートで判断して30〜80ギガバイト)。 私は、問題は標準::ベクトルが負の32ビット整数値にリサイズされていると考えています。この動作を示す唯一のプラットフォームはSolarisです(おそらく、このような連続したメモリのまとまりをうまく割り当てることができる唯一のプラットフォームです)。 std :: vectorをmy classにグローバルに置き換えて、すべての呼び出しを実際のベクトルに委譲し、疑わしい割り当てがあるのを見てください(size > 0x7FFFFFFFu)?場合によっては、size_tresize()メソッドを使用するコンストラクタを選択的に置き換えることができますか?多分、グローバルオペレーターを新しいものに乗っ取ることさえ可能でしょうか?巨大なメモリ割り当てを追跡するためのグローバル演算子のオーバーライド?

+1

32ビット値でIMOの結果が30-80ギガバイトにならない場合は、64ビットを意味しますか? –

+0

0xFFFFFFFFの8バイト構造の配列は〜34ギガバイトを要します。 –

+0

私は訂正した –

答えて

5

なぜこのようなことをしないのですか?すぐに問題を見つけるだろうifにブレークポイントを設定する

void *operator new(size_t size) 
{ 
    // if (size > MAX_SIZE) ... 
    return malloc(size); 
} 

void *operator new [](size_t size) 
{ 
    // if (size > MAX_SIZE) ... 
    return malloc(size); 
} 

+0

はい、これは達成したいことです。もちろん、 'operator new'は既にプラットフォームの標準ライブラリに定義されているので、単に2番目の実装を提供することはできません。 –

+1

はいできます。やってみました?リンクエラーが出ますか? – detunized

+0

もし私がそれを単純に行うことができれば素晴らしいだろう。私が試してみます。 –

2

構築時にベクターにカスタムアロケータを提供することができます。

最初に、std::allocatorに委任し、要求されたメモリサイズをファイアウォールすることができます。

+0

あなたは、問題は私がコードのどの部分が誤っているのか分からないことがわかります。ベクターが使用されているどこでもカスタムアロケータを使用してコードベース全体(サードパーティのライブラリを含む?)を変更することはほとんど不可能です。 –

+0

はい、それは難しいです。あなたのように読んだqは、これがどのベクトルであるかをすでに知っているかもしれません。コールスタックを作成してヒープブロックの属性を設定する方法はありますか? –

+0

不審な状態を検出したときにコールスタックを記録できます。問題は、ベクトルを使用してすべての単一のクラスを変更することなく、グローバルにそれを検出する方法です。 –

0

問題のプラットフォームでstd::vectorクラスの実装を見てください。各インプリメンテーションは、メモリ管理を別々に扱います(たとえば、ベクトルの現在の割り当てサイズ外にオブジェクトを追加すると、現在割り当てられているスペースの2倍)。オブジェクトが十分に大きい場合や、ベクトルに多数のエントリが追加されている場合は、コンピュータ上の利用可能な(連続した)メモリを超えて割り当てることができます。そのような場合は、そのベクトルのカスタムアロケータを調べる必要があります。

大きなアイテムをベクトルに格納する場合は、別のコレクション(たとえばstd::list)を探したり、実際のオブジェクトの代わりにポインタを格納したりすることをおすすめします。

+0

私が解決しようとしている問題は、少ないメモリを使用するようにコードを修正する方法ではありません。私は効果的に 'vector.resize((size_t)( - 1))'を実行するバグのあるコードを見つけようとしています。その部分が特定されたら、修正するのは簡単な作業でなければなりません。 –

+0

条件付きブレークポイント機能を持つデバッガにアクセスできる場合、そのトリックが実行されます。それ以外の場合は、コレクションを半分にカットし、同じ問題が発生したかどうかをテストしてみてください。問題が見られるまで残りのアイテムの半分までコレクションを増やしてください。私の嫌な反応は、在庫アロケータが現在の容量を倍増させてコレクションの容量を増やすことに割り当てられている途中で、割り振るために連続したメモリが不足していることです。 –

+0

QA環境でお客様のサイトでコードが実行されます。私はその実行結果(ログファイル)にアクセスできますが、デバッガで実行するよう要求することはできません。 –

0

割り当てを追跡するためにに独自のallocatorタイプを指定することができます。 しかし、私はそれが理由だとは思わない。最初に、サイズ(30〜80GB)を見ると、64ビットコードだと結論づけられます。どのようにして32ビットの負の整数値で64ビットのベクタサイズにすることができましたか?まず64ビットに昇格して値を保持しますか?第2に、この問題がSolarisでのみ発生した場合は、別の問題を示す可能性があります。私が知る限り、Solarisは割り当て時にメモリをコミットする唯一のOSであり、他のオペレーティングシステムはそれらのメモリページが実際に使用されるまで割り当てられたアドレススペースをマークするだけです。だから私は未使用の割り当てを探します。

+0

どのようにして負の32ビット値をベクトルサイズにすることができますか?このようなもの: 'uint32_t count =(uint32_t)GetNumberOfThings(); std :: vector things(Thing()、count); 'GetNumberOfThings'がエラーのときに-1を返すとき。そして、既存のコードベースは、32ビットサイズの変数を多く使用し、32ビットサイズを使用するカスタムベクターの実装もしています。問題は、問題のコードを追跡することです... –

関連する問題