修正日: 07/10/23
MallocDebug
Performance Tools入門 その1
7. バッファオーバーランの検出
MallocDebugでアプリケーションを起動する際動的にリンクされるmalloc(/usr/lib/libMallocDebug.A.dylib)は、バッファオーバーランを検出するために、割り当てるメモリの前後8バイトに保護ワード0xdeadbeef、0xbeefdeadを配置します(図15)。MallocDebugは保護ワード部分に書き込みが行われたメモリブロックをバッファオーバーラン/アンダーランとして検出することができます。【図15】 deadbeef / beefdead
(1)試してみる
サンプル「mLeaker」をMallocDebugで起動し、「Buffer overrun」ボタンを押してください。バッファオーバーランを意図的に発生させます。MallocDebugのAll Allocationsポップアップボタンで「Over/underruns」を選択し、オーバーランが発生した箇所を確認してみてください(図16)。
【図16】 バッファオーバーランの結果
8.メモリ解放時のデータクリア
MallocDebugは解放したメモリに即座に0x55を書き込み、データをクリアする機能があります。通常のアプリケーションの動作ではメモリブロックを解放しても、そのブロックが新たなメモリブロックとして割り当てられるまでは、解放前のデータが残った状態になります。そのためすでに解放したブロックに誤ってアクセスしても、何の問題もなく動いてしまうことがあります。このような場合、不正なアクセスが発生してもアプリがクラッシュするタイミングがまちまちになり、いつ、どこで問題が発生しているのかを特定するのが困難になりがちです。MallocDebugで動作させるとメモリが解放されると同時に内容がクリアされるため、不正なアクセスが発生するとすぐにアプリケーションがクラッシュするようになります。このためバグの箇所を特定しやすくなるというメリットがあります。
普通に操作した時は問題無いのにMallocDebugで動かすと頻繁にクラッシュする、という場合はこの種のバグの可能性が高いので注意しましょう。
(1)設定
Preferenceパネルの「Clear malloc'd memory when freed」チェックボックスででクリアするかどうかをオンオフします(オンでクリアします)。MallocDebugから対象アプリケーションを起動する際の設定が有効になり、起動後のオンオフは反映されません。なおオフにしてもMallocDebugを再起動するとまたオンになるので注意します。
(2)試してみる
サンプル「mLeaker」をMallocDebugで起動し、「alloc」ボタンを押してください。@”This is test string for Freed Memory!!!”というNSStringを作成しますので、MallocDebugでそのメモリブロックを探してメモリインスペクタで表示します(78バイトのブロックが生成されますー図17)。
【図17】作成したメモリブロック
次にreleaseボタンを押します。生成したfreedStringを解放しますので、解放後表示しておいたメモリブロックの中身がクリアされていることを確認しましょう(図18ーメモリインスペクタは自動で更新はされないので、ForwordしてBackするなりして描画を手動で更新します)。
- (IBAction)makeFreedString:(id)sender
{
NSZone *zone=NSCreateZone(NSPageSize(), NSPageSize(), YES);
NSSetZoneName(zone, @"FreedStringZone");
freedString=[[NSString stringWithString:
@"This is test string for Freed Memory!!!"]
copyWithZone:zone];
}
【図17】作成したメモリブロック
次にreleaseボタンを押します。生成したfreedStringを解放しますので、解放後表示しておいたメモリブロックの中身がクリアされていることを確認しましょう(図18ーメモリインスペクタは自動で更新はされないので、ForwordしてBackするなりして描画を手動で更新します)。
- (IBAction)releaseFreedString:(id)sender
{
[freedString release];
}
【図18】解放後のメモリブロック