troushoo

WPR/WPA を用いた、アプリのメモリリークの調査方法

WPR/WPA を用いた、アプリのメモリリークの調査方法

概要

WPR/WPA を使用した、アプリのメモリリークの調査方法を紹介します。
解放が行われていないヒープ領域を割り当てたコールスタックがわかり便利です。

内容

WPR/WPA とは?
WPR/WPA は、パフォーマンスのトラブルシューティングに使える強力なツールで、Microsoft よりフリーで公開されています。WPR はWindows Performance Recorder の略で、WPA はWindows Performance Analyzer の略です。
WPR/WPA はWindows SDK に含まれています。

(ダウンロード・インストール方法について特に迷うところはありませんが、具体的な方法につきましては以前のブログにも記載しております。)

WPR/WPA を用いた、アプリのメモリリークの調査方法
以下、二つのセクションに分けて、実際の調査方法を紹介します。
1. WPR を用いてトレース情報収取
2. WPA を用いて、収取したトレース情報の解析

[1. WPR を用いてトレース情報収集]
まずは、メモリリークの発生が疑われるアプリのトレース情報を、以下の方法で収集します。

1.1. ヒープのトレースを有効にするために、トレースの取得したいプロセスに対し、以下のレジストリの設定を行います。

キー HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<プロセス名>
名前 TracingFlags
種類 DWORD
1
トレースの取得したいプロセスに対し、レジストリの設定を行う

1.2. C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\WPRUI.exe を起動します。
WPRUI.exe を起動

1.3. “More options” をクリックします。
More options をクリック

1.4. “Heap usage” にチェックを入れ、”Start” をクリックし、情報収集を開始します。
Heap usage にチェックを入れStart

1.5. メモリリークが疑われるアプリを実行します。

1.6. “Save” を押し、情報の収集を終了します。
Save を押し、情報の収集を終了

1.7. “Save” を押すと、”File Name” のパスに、トレース情報が格納されたETLファイルが保存されます。
Save を押すと、”File Name” のパスに、トレース情報が格納されたETLファイルが保存される

[2. WPA を用いて、収集したトレース情報の解析]
2.1. 上記1.7. で保存したETLファイルをダブルクリックします。すると、WPA が起動します。
ETL ファイルをダブルクリック

2.2. “Trace” → “Load Symbols” を実行し、シンボルをロードします。
Load Symbols

2.2. “Memory” の左の三角形をクリックし、”Memory” を展開します。
Memory を展開

2.3. 展開された中にある”Heap Allocations” をダブルクリックします。
Heap Allocations をダブルクリック

2.4. すると、右側に”Heap Allocations” の詳細が表示されます。
右側にHeap Allocations の詳細が表示される

2.5. アプリ名の右の四角の部分をクリックし、色を有効にします。(下のスクリーンショット参照)
すると、右のグラフに、解放されていないヒープのサイズが時系列で表示されます。
右肩上がりになっていたら、メモリリークの発生が疑われます。
グラフでメモリリークの発生を確認

2.6. 詳細を調べるために、表の一番上の列を右クリックし、”Type”と”Stack” の列を追加します。
Type とStack の列を追加

2.7. わかりやすさのために、”Type” と”Stack” の行ドラッグアンドドロップして、下図の位置に移動します。
Type とStack の列を移動

2.8. ここで重要になるのは”Type” の”AIFO” です。
AIFO はAllocated Inside Freed Outside の略で、トレース中(= Inside) にヒープが割り当てられ(= Allocated)、トレースの後(= Outside) にフリーされた(= Freed) という意味です。
すなわち、メモリリークの発生が疑われる部分になります。

今回の例を見ると、AIFO が 約42MB あることがわかります。
AIFO が重要

2.9. “AIFO” を展開し、”Stack” も展開します。
すると、”MyHeapTest.exe!MyAlloc” の関数が、約42M のメモリを割り当てていることがわかります。
MyHeapTest.exe!MyAllocが、メモリを多く割り当てている

2.10. この情報をもとに、ソースコードを確認してみると、この例では、実際にフリーされないコードという事がわかります。

#include "stdafx.h"
#include <Windows.h>

void MyAlloc(){
HANDLE hHeap[3000];
VOID *pHeap;
int i = 0;


  //Enter を押すごとに1024000 バイト割り当てる
  while (true){
hHeap[i] = HeapCreate(NULL, 0, 0);

  pHeap = HeapAlloc(hHeap[i], HEAP_ZERO_MEMORY, 1024000); //1024000 バイト割り当てる

i++;
getchar();
}
}

int _tmain(int argc, _TCHAR* argv[])
{
MyAlloc();
return 0;
}


情報元
Recording for Heap Analysis (英語)
関連記事
WPR/WPA を用いた、アプリが何を待っているかを調べる方法


  1. 2014/05/20(火) 22:11:10|
  2. ツール
  3. | トラックバック:0
  4. | コメント:0
<<lsass.exe のダンプからユーザーパスワードを抽出 :mimikatz | ホーム | 追加ソフトをインストールすることなく、Windows の自マシン間の通信をキャプチャーする方法>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
https://troushoo.blog.fc2.com/tb.php/172-ef1b3bc2
この記事にトラックバックする(FC2ブログユーザー)

スポンサーリンク

最新記事

月別アーカイブ

カテゴリ

ツール (114)
ネットワーク (54)
Wireshark (48)
AD (36)
Linux (45)
WinDbg (46)
SOS・Psscor2/Psscor4 (25)
Visual Studio (56)
Tips (32)
コンテナ (4)
Azure (17)
.NET (24)
Python (9)
Java (5)
SQL (6)
事例 (1)
英語 (1)
About Me (1)
未分類 (0)

全記事表示リンク

全ての記事を表示する

検索フォーム

RSSリンクの表示

リンク

このブログをリンクに追加する