2

ソースコードでメモリの割り当て/割り当て解除を監視する最良の方法は何ですか? 大量のメモリを動的に割り当てる C++ プログラムがあり、どのクラスからどのオブジェクトがメモリを取得して解放しているかを追跡したいと考えています。

私のプログラムの出力に欲しいものは次のとおりです。

Creating Object from ClassA, Memory Usage ...
Creating Object from ClassB, Memory Usage ...
...
Freeing  Object from ClassA, Memory Freed ...

私が今していることは、単純にグローバルな new 演算子をオーバーロードすることですが、あまり安全ではないと聞きました。さらに、すべてのクラスを変更する必要のない方法が必要です (つまり、基本クラスを使用し、すべてのクラスに文字列変数 ClassName があります)。

--------------------------------------編集------------ --------------------------

1- 外部ツールを使用したくないので、コード内で行う必要があります。

2- グローバル new 演算子をオーバーロードした場合、クラスまたは他のメンバーの名前にアクセスするにはどうすればよいですか?

4

4 に答える 4

2

アプリケーション検証ツールと呼ばれる MS ツールを参照してください。また、VS2010 プロファイラーも参照してください。

于 2012-08-29T16:32:08.147 に答える
1

開発のみで行うか、本番環境で行うか、およびパフォーマンス要件が何であるかによって大きく異なります。Linux での開発では、通常、Valgrind の Massifから開始します。よりカスタムなソリューションやプロダクション モードを検討している場合は、malloc/calloc/realloc オーバーライド コード (私の例はこちら) とlibunwindを組み合わせることを検討できます。

于 2012-08-29T16:37:42.750 に答える
1

メモリリークを追跡するためのこのツールは嫌いですが、 allocs/dellocs を監視するには、必要なことを行う必要があります: UMDH

于 2012-08-29T16:36:54.667 に答える
1

2- グローバル new 演算子をオーバーロードした場合、クラスまたは他のメンバーの名前にアクセスするにはどうすればよいですか?

できません。new 演算子と delete 演算子は単純な関数呼び出しではないことを理解する必要があります。実際には、次のような構文MyClass* p = new MyClass();は次と同等です。

MyClass* p = (MyClass*) malloc(sizeof(MyClass)); // A) allocate the memory.
new(p) MyClass(); // B) call constructor (via placement-new syntax (to illustrate)).

adelete p;は次と同等です。

p->~MyClass();  // C) call destructor.
free(p);        // D) free the memory.

new-delete 演算子をオーバーロードする場合、コンパイラが実際にオーバーロードできるのは、それぞれステップ A) と D) だけです。つまり、カスタム new 演算子の本体に到達すると、オブジェクトはまだ作成されていないため、メモリ内のアドレスを除いて、オブジェクトに関する情報 (クラス、名前など) にアクセスしたり出力したりすることはできません。 、オーバーロードされた new で印刷できます。同様に、カスタムの削除演算子に到達するまでに、オブジェクトは破棄されており、特に仮想関数または文字列値を使用する場合は、そのメモリにまだぶら下がっている可能性のある情報を使用しようとする試みは未定義の動作です。

実際、このアプローチでできる最善の方法は、new 演算子で作成されたポインターを出力し、delete 演算子によって削除されたポインターを出力することです。

また、他の人が述べたように、new-delete 演算子内で操作を行うときは、無限再帰に注意する必要があります。たとえば、次のような単純な行です。

std::cout << "Created pointer: " << reinterpret_cast<std::size_t>(p) << std::endl;

ほとんどの場合、new と delete の多くの呼び出しが発生します (一時的な文字列の作成、バッファーの拡張など)。

したがって、おそらく、出力したいログ メッセージを new-delete を発生させずに出力する賢い方法を考え出すか、new-delete 演算子のオーバーロードを次のクラスのみに制限する必要があります。あなたのフレームワーク。後者の場合、最も簡単な方法は、基本クラスに配置することです。もう 1 つのオプションは、MACRO マジックを少し使用することですが、これは依然として煩雑で扱いにくいものです。

そして、この時点で、この作成と削除のロギングを処理する基本クラスを (すべてのライブラリのクラスに対して) 作成する必要がある場合 (または、作成する各クラスに配置する一連の MACRO を作成する必要がある場合)、次のようにします。これらのログメッセージを出力する場所として代わりにコンストラクター/デストラクタを使用し、new-delete 演算子はそのままにしておきます。

1- 外部ツールを使用したくないので、コード内で行う必要があります。

なぜだめですか?外部ツール (Valgrind のような VM、または一般的なプロファイラー / メモリ トレーサー) は、あなたよりもはるかに優れた、邪魔にならない仕事をする可能性が非常に高いです。

于 2012-08-29T17:17:34.550 に答える