web-dev-qa-db-ja.com

C ++メモリ割り当てを追跡する

C++プログラムでメモリ割り当てを追跡する方法を探しています。私はnotメモリリークに興味がありますが、これはほとんどのツールが見つけようとしているもののようですが、アプリケーションのメモリ使用量プロファイルを作成しています。理想的な出力は、関数名の大きなリストに加えて、時間の経過とともに割り当てられた最大バイト数のいずれか、またはより適切な、時間の経過に伴うヒープのグラフィカルな表現です。横軸は時間、縦軸はヒープスペースです。すべての関数は独自の色を取得し、割り当てられたヒープバイトに従って線を描画します。同様に、割り当てられたオブジェクトタイプを識別するためのボーナスポイント。

アイデアは、メモリのボトルネックを見つけること/どの関数/スレッドが最もメモリを消費するかを視覚化することであり、さらなる最適化の対象とすべきです。

Purify、BoundsChecker、およびAQTimeについて簡単に説明しましたが、それらは私が望んでいるものではないようです。 Valgrindは適切に見えますが、私はWindowsを使用しています。 Memtrack は有望に見えますが、ソースコードを大幅に変更する必要があります。

私のグーグルスキルは私を失敗させたに違いありません、それはそれほど珍しいリクエストではないように思われますか?そのようなツールを作成するために必要なすべての情報は、プログラムのデバッグシンボルとランタイムAPI呼び出しからすぐに利用できるはずです-いいえ。

47
BuschnicK

ゲーム開発のためのPCのメモリ使用量の監視 には、私が探していたもののほぼ完璧な例が含まれています。実行に時間がかかりましたが、記事の著者は非常に役に立ちました。ツールのソースコードは、ここで Memtracer にあります。

また、 [〜#〜] sweng [〜#〜] (ソフトウェアエンジニアリングメーリングリスト)で多くの有益な回答を得ました。スレッドは「[Sweng-Gamedev] C++メモリ使用量を監視しますか?」と呼ばれます。

7
BuschnicK

ValgrindとそのツールMassifを使用します。その出力例(その一部):

99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->49.74% (10,000B) 0x804841A: main (example.c:20)
| 
->39.79% (8,000B) 0x80483C2: g (example.c:5)
| ->19.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->19.90% (4,000B) 0x8048431: main (example.c:23)
| |   
| ->19.90% (4,000B) 0x8048436: main (example.c:25)
|   
->09.95% (2,000B) 0x80483DA: f (example.c:10)
  ->09.95% (2,000B) 0x8048431: main (example.c:23)

したがって、詳細な情報を取得できます。

  • WHOがメモリを割り当てました(関数:上記の例のg()、f()、およびmain());また、機能の割り当てにつながる完全なバックトレースを取得します。
  • メモリが行ったデータ構造(上記の例ではデータ構造なし)
  • それが起こった時、
  • 割り当てられたすべてのメモリのPERCENTAGE(g:39.7%、f:9.95%、main:49.7%)。

マシフマニュアル

ヒープ割り当てとスタック割り当てを追跡できます(デフォルトではオフになっています)。

PS。 Windowsを使用していると読みました。ただし、可能性のあるツールから得られるものの写真を提供するため、答えは残しておきます。

31
anon

マイクロソフトは、メモリトラッキング機能を十分に文書化しています。ただし、何らかの理由で、それらは開発者コミュニティではあまり知られていません。これらはCRTデバッグ関数です。適切な出発点は CRT Debug Heap functions です。

詳細については、次のリンクを確認してください

  1. ヒープ状態レポート関数
  2. ヒープ割り当て要求の追跡 。おそらくこれがあなたが探している機能です。
19
Nitin Bhide

汎用のC++メモリトラッカーの場合、以下をオーバーロードする必要があります。

global operator new
global operator new []
global operator delete
global operator delete []
any class allocators
any in-place allocators

トリッキーなビットは有用な情報を取得しています。オーバーロードされた演算子はアロケーターのサイズ情報と削除用のメモリポインターのみを持っています。 1つの答えは、マクロを使用することです。知っている。不快な。例-すべてのソースファイルからインクルードされるヘッダーに配置します。

#undef new

void *operator new (size_t size, char *file, int line, char *function);
// other operators

#define new new (__FILE__, __LINE__, __FUNCTION__)

そしてソースファイルを作成します:

void *operator new (size_t size, char *file, int line, char *function)
{
  // add tracking code here...
  return malloc (size);
}

上記は、クラススコープでnew演算子が定義されていない場合にのみ機能します。クラススコープにある場合は、以下を実行します。

#define NEW new (__FILE__, __LINE__, __FUNCTION__)

「新しいタイプ」を「新しいタイプ」に置き換えますが、これには多くのコードを潜在的に変更する必要があります。

マクロなので、メモリトラッカーの削除は非常に簡単で、ヘッダーは次のようになります。

#if defined ENABLED_MEMORY_TRACKER
#undef new

void *operator new (size_t size, char *file, int line, char *function);
// other operators

#define NEW new (__FILE__, __LINE__, __FUNCTION__)
#else
#define NEW new
#endif

実装ファイル:

#if defined ENABLED_MEMORY_TRACKER
void *operator new (size_t size, char *file, int line, char *function)
{
  // add tracking code here...
  return malloc (size);
}
endif
13
Skizz

これも試してください: Memory Validator

1
Naveen

Mac OS Xでは、コードプロファイリングツールSharkを使用してこれを行うことができます、IIRC。

0
paxos1977

「経時的なヒープのグラフィカルな表現」-探しているものに近いものが Intel(R)Single Event API に実装されており、詳細は この記事 にあります。 (ここに置くのはかなり大きい)。 Memory block allocations over time

ブロックサイズごとの割り当てのタイムラインを表示し、コード全体にマークを追加して、全体像をよりよく理解できます。

0
araud

Xcodeでは、Instrumentsを使用して、割り当て、VM使用状況、およびその他のいくつかのパラメーターを追跡できます。iOS開発者の間で最も人気がありますが、試してみる価値があります。

0
Totoro

Visual Studio IDEは、組み込みのヒーププロファイリングサポート(2015年以降)を備えています。これは、おそらく最も簡単に開始できます。 /方法。

heap profiling

CRTにはデバッグとプロファイルのサポートもあり、これはより詳細でより低レベルです。他のツールを使用して、データを追跡し、結果をプロットできます。

特に、_CrtMemCheckpointおよび関連する関数。

0
gavinb