私は大きなモノリシックアプリケーションの特別なビルドを制作しようとしています。私が解決しようとしている問題は、難しい再現性のある膨大なメモリ割り当てを追跡することです(OSレポートで判断して30〜80ギガバイト)。 私は、問題は標準::ベクトルが負の32ビット整数値にリサイズされていると考えています。この動作を示す唯一のプラットフォームはSolarisです(おそらく、このような連続したメモリのまとまりをうまく割り当てることができる唯一のプラットフォームです)。 std :: vectorをmy classにグローバルに置き換えて、すべての呼び出しを実際のベクトルに委譲し、疑わしい割り当てがあるのを見てください(size > 0x7FFFFFFFu)
?場合によっては、size_t
とresize()
メソッドを使用するコンストラクタを選択的に置き換えることができますか?多分、グローバルオペレーターを新しいものに乗っ取ることさえ可能でしょうか?巨大なメモリ割り当てを追跡するためのグローバル演算子のオーバーライド?
答えて
なぜこのようなことをしないのですか?すぐに問題を見つけるだろう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);
}
。
はい、これは達成したいことです。もちろん、 'operator new'は既にプラットフォームの標準ライブラリに定義されているので、単に2番目の実装を提供することはできません。 –
はいできます。やってみました?リンクエラーが出ますか? – detunized
もし私がそれを単純に行うことができれば素晴らしいだろう。私が試してみます。 –
構築時にベクターにカスタムアロケータを提供することができます。
最初に、std::allocator
に委任し、要求されたメモリサイズをファイアウォールすることができます。
あなたは、問題は私がコードのどの部分が誤っているのか分からないことがわかります。ベクターが使用されているどこでもカスタムアロケータを使用してコードベース全体(サードパーティのライブラリを含む?)を変更することはほとんど不可能です。 –
はい、それは難しいです。あなたのように読んだqは、これがどのベクトルであるかをすでに知っているかもしれません。コールスタックを作成してヒープブロックの属性を設定する方法はありますか? –
不審な状態を検出したときにコールスタックを記録できます。問題は、ベクトルを使用してすべての単一のクラスを変更することなく、グローバルにそれを検出する方法です。 –
問題のプラットフォームでstd::vector
クラスの実装を見てください。各インプリメンテーションは、メモリ管理を別々に扱います(たとえば、ベクトルの現在の割り当てサイズ外にオブジェクトを追加すると、現在割り当てられているスペースの2倍)。オブジェクトが十分に大きい場合や、ベクトルに多数のエントリが追加されている場合は、コンピュータ上の利用可能な(連続した)メモリを超えて割り当てることができます。そのような場合は、そのベクトルのカスタムアロケータを調べる必要があります。
大きなアイテムをベクトルに格納する場合は、別のコレクション(たとえばstd::list
)を探したり、実際のオブジェクトの代わりにポインタを格納したりすることをおすすめします。
私が解決しようとしている問題は、少ないメモリを使用するようにコードを修正する方法ではありません。私は効果的に 'vector.resize((size_t)( - 1))'を実行するバグのあるコードを見つけようとしています。その部分が特定されたら、修正するのは簡単な作業でなければなりません。 –
条件付きブレークポイント機能を持つデバッガにアクセスできる場合、そのトリックが実行されます。それ以外の場合は、コレクションを半分にカットし、同じ問題が発生したかどうかをテストしてみてください。問題が見られるまで残りのアイテムの半分までコレクションを増やしてください。私の嫌な反応は、在庫アロケータが現在の容量を倍増させてコレクションの容量を増やすことに割り当てられている途中で、割り振るために連続したメモリが不足していることです。 –
QA環境でお客様のサイトでコードが実行されます。私はその実行結果(ログファイル)にアクセスできますが、デバッガで実行するよう要求することはできません。 –
割り当てを追跡するためにに独自のallocator
タイプを指定することができます。 しかし、私はそれが理由だとは思わない。最初に、サイズ(30〜80GB)を見ると、64ビットコードだと結論づけられます。どのようにして32ビットの負の整数値で64ビットのベクタサイズにすることができましたか?まず64ビットに昇格して値を保持しますか?第2に、この問題がSolarisでのみ発生した場合は、別の問題を示す可能性があります。私が知る限り、Solarisは割り当て時にメモリをコミットする唯一のOSであり、他のオペレーティングシステムはそれらのメモリページが実際に使用されるまで割り当てられたアドレススペースをマークするだけです。だから私は未使用の割り当てを探します。
どのようにして負の32ビット値をベクトルサイズにすることができますか?このようなもの: 'uint32_t count =(uint32_t)GetNumberOfThings(); std :: vector things(Thing()、count); 'GetNumberOfThings'がエラーのときに-1を返すとき。そして、既存のコードベースは、32ビットサイズの変数を多く使用し、32ビットサイズを使用するカスタムベクターの実装もしています。問題は、問題のコードを追跡することです... –
- 1. 'new []'演算子でメモリを割り当てる
- 2. ヒープ上のメモリ割り当て用new演算子
- 3. 新しい演算子ヒープ内の内部メモリ割り当て
- 4. シーケンシャルな 'new'演算子は連続したメモリを割り当てますか?
- 5. 条件演算子の割り当て
- 6. ペアテンプレートのオーバーロード割り当て(=)演算子
- 7. 割り当てられたメモリの巨大なブロックを見つける
- 8. 論理演算子と割り当て
- 9. 演算子のオーバーロードにメモリが割り当てられていますか?
- 10. 巨大メモリの使用量を追跡できません
- 11. 代入演算子でのstd :: shared_ptrの割り当て
- 12. F#:静的メソッドのオーバーロードまたは条件付き演算子を使用したグローバル演算子のオーバーライド
- 13. C#6.0ヌル伝播演算子とプロパティの割り当て
- 14. PHP三項演算子オブジェクトの割り当て
- 15. C++のオーバーロード割り当てとラウンドブラケット演算子
- 16. openCL CPUの最大メモリ割り当て
- 17. 巨大なページを使用して割り当てられたメモリには制限がありますか?
- 18. C++演算子のオーバーライド
- 19. 等価演算子のオーバーライド
- 20. Rubyのオーバーライド==演算子
- 21. new()演算子を使用してメモリを割り当てるときにmudflapがコアダンプをスローする
- 22. 動的割り当てポインタを持つクラスに演算子のオーバーライドを適用します。
- 23. 配列の配列のための<<演算子のオーバーライド
- 24. グローバルな型キャスト演算子のオーバーロード?
- 25. C++で動的に割り当てられた型のオーバーロード+演算子
- 26. 移動割り当て私はこの見たコピー代入演算子
- 27. グローバルnew演算子は、割り当てられたオブジェクトの型特性に基づいてオーバーライドできますか?
- 28. 割り当て/割り当て解除を追跡できますか?
- 29. オブジェクトの関数に論理演算子を割り当てる方法は?
- 30. 演算子=のための一致なし、コンストラクタは、私がLinkedListのクラスを作成する必要がありました割り当てのためにポインタ
32ビット値でIMOの結果が30-80ギガバイトにならない場合は、64ビットを意味しますか? –
0xFFFFFFFFの8バイト構造の配列は〜34ギガバイトを要します。 –
私は訂正した –