Visual Studio C++でメモリリークの検出 crtdbg.h CrtSetDbgFlag C言語のアクセス違反の調査

プログラミング
スポンサーリンク

Visual Studio C++でメモリリークの検出 crtdbg.h CrtSetDbgFlagの使い方の紹介です。

 

スポンサーリンク

Visual Studio C++でメモリリークの検出

Javaならいざ知らず、CやC++でプログラムをしていて誰も犯してしまうバグの一つがメモリリークだと思います。

 

Visual Studioにはメモリリークを検出するための便利な機能があります。

 

以下をプログラムの先頭に入れておきます。

 

 

mainの先頭に以下のコードを入れておきます。

 

 

メモリリーク検出のサンプルプログラムは以下の通りです。

 

 

上記のプログラムを実行してみると「出力」のエリアでは以下の通り表示されます。

Detected memory leaks!
Dumping objects ->
C:\Users\xxxx\yyyy\memoryleak.cpp(11) : {120} normal block at 0x006CE2C8, 40 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
プログラム ‘[2180] MemoryLeakCheck.exe’ はコード 0 (0x0) で終了しました。

 

 

delete ptr; のコメントを外して実行すると以下の通りになります。

プログラム ‘[5084] MemoryLeakCheck.exe’ はコード 0 (0x0) で終了しました。

 

 

このサンプルのようにメモリリークしている関数があるとソースと行を表示してくれるのでとても便利です。

 

 

ちなみに上記のプログラムで

 

delete ptr;
delete ptr;

 

のようにフリーしたポインターをさらにフリーしてみると以下のにエラーが表示されます。

 

ハンドルされない例外が0x57924F98(msvcr110d.dll)で発生しました
(MemoryLeakCheck.exe 内):0xC0000005: 場所 0x00008117 の読み取り中に
アクセス違反が発生しました。

 

 

このようなエラーを引き起こさないように、mallocとfree、newとdeleteは必ず対で使うように注意します。

 

デバッグモードでのメモリの内容

ところで、マイクロソフトのコンパイラ/OSによるデバッグモードでのメモリの内容は以下の通りです。

 

名前 内容
0xCD Clean Memory
クリーンメモリ
mallocやnewでメモリが確保されたけれどまだ使われていない状態。
0xDD Dead Memory
デッドメモリ
deleteやfreeで解放されたメモリ。
0xED
0xBD
Aligned Fence
アラインフェンス
アラインメモリ確保における「No man’s land」。
0xFD Fence Memory
フェンスメモリ
確保されたメモリをラップするもの。「No man’s land」として知られる。つまり、プログラムではアクセスできない領域。
0xFD
0xFE
Buffer slack
バッファスラック
メモリバッファにスラックスペースを入れるために使われる。
0xCC /GZオプションでコンパイルされたときに、初期化されていない領域は自動的にこの値がセットされる。
0xAB Allocated Block
アロケートブロック
CランタイムではなくOSにより実行される。
LocalAlloc()により確保されるメモリ。
0xBAADF00B Bad Food
バッドフード
CランタイムではなくOSにより実行される。
LMEM_FIXED付きのLocalAlloc()により確保されるメモリ。
0xFEEEFEEE CランタイムではなくOSにより実行される。
ある目的のあるメモリだが、HeapAlloc()やLocalAlloc()では確保されていない、あるいはHeapFree()で解放されたメモリ。

 

これらのメモリの値を知っていると、デバッグ時にメモリがどのような状態にあるのかがわかって便利です。

 

メモリウィンドウの表示方法

Visual Studioでメモリウィンドウは以下のようにします。

 

Visual Studioのメニューから

[デバッグ] メニュー→ [ウィンドウ] →[メモリ] を押します。

 

[メモリ 1]、[メモリ 2]、[メモリ 3]、または [メモリ 4] を押します。

各 [メモリ] ウィンドウは、任意の順序で開くことができます。

 

例えば上記のプログラムでは次のようになります。

メモリを確保した直後は、0xfdfdfdfdで囲まれた領域に0xcdで32バイトメモリが確保されていることがわかります。

 

次にdeleteが実行された直後は次の通りです。

 

先ほど0xcdで確保されていた場所が、すべて0xddに置き換わりました。

 

デバッグモードでこのようにヒープメモリが扱われていることを知っているとメモリリークなどの検出・デバッグに便利です。

 

まとめ:メモリリーク

メモリリークはプログラムの初心者から上級者まで常に作ってしまうバグとして注意しましょう。

プログラムにおいて単純に動作することと運用として使えることは異なります。

 

メモリリークバグのあるプログラムを一ヶ月ぐらい稼働していると見た目は安定して運用出来ていても、プログラムが徐々にOSのメモリを食いつぶして忘れたことにOSごとフリーズすることがあります。

メモリリークは厳密なチェックが望ましいですが、おおざっぱには、プログラム実行時に特定の操作を行う都度に、Windowsのタスクマネージャから見たメモリが増えていないかだけでもチェックしましょう。

 

プログラミングの無料レッスン体験

 

約8,000名の受講生と80社以上の導入実績のあるプログラミングやWebデザインのオンラインマンツーマンレッスンCodecamp

<Codecampの特徴>

1 現役エンジニアによる指導

2オンラインでのマンツーマン形式の講義

3大手企業にも導入されている実践的なカリキュラム

↓無料体験レッスン実施中です。

プログラミングのオンラインスクールCodeCamp

 

 

 

コメント