実行時検査を使用するには、使用したい検査の種類を指定します。
メモリー使用状況とメモリーリークの検査をオンにするには、次を入力します。
(dbx) check -memuse |
MUC か MLC がオンになっている場合、showblock コマンドを実行する、所定のアドレスにおけるヒープブロックに関する詳細情報を表示できます。この詳細情報では、ブロックの割り当て場所とサイズを知ることができます。詳細については、「showblock コマンド」を参照してください。
(dbx) check -access |
メモリーリーク、メモリー使用状況、およびメモリーアクセスの各検査をオンにするには、次のように入力します。
(dbx) check -all |
詳細については、「check コマンド」を参照してください。
(dbx) uncheck -all |
詳細については、「uncheck コマンド」を参照してください。
目的のタイプの RTC を有効にしてテストするプログラムを実行します。この場合、ブレークポイントを設定してもしなくてもかまいません。
プログラムは正常に動作しますが、それぞれのメモリーアクセスが発生する直前にその妥当性チェックが行われるため、動作速度は遅くなります。無効なアクセスを検出すると、dbx はそのエラーの種類と場所を表示します。 制御はユーザーに戻ります (dbx 環境変数 rct_auto_continue が on になっている場合を除く (「dbx 環境変数の設定」を参照))。
次に、dbx コマンドを実行します。where コマンドでは現在のスタックトレースを呼び出すことができます。また print を実行すれば変数を確認できます。エラーが致命的でなければ、 cont コマンドでプログラムの処理を続行します。プログラムは次のエラーまたはブレークポイントまで、どちらか先に検出されるところまで実行されます。詳細については、「cont コマンド」を参照してください。
rtc_auto_continue 環境変数が on に設定されている場合、RTC はそのままエラーを求めて自動的に続行されます。 検出したエラーは、dbx 環境変数 rtc_error_log_name で指定したファイルにリダイレクトされます (「dbx 環境変数の設定」を参照)。デフォルトログファイル名は、/tmp/dbx.errlog.uniqueid です。
RTC エラーの報告が不要な場合は、suppress コマンドを使用します。詳細については、「suppress コマンド」を参照してください。
次の例は、hello.c と呼ばれるプログラムのメモリーアクセス検査とメモリー使用状況検査をオンにする方法を示しています。
% cat -n hello.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 char *hello1, *hello2; 6 7 void 8 memory_use() 9 { 10 hello1 = (char *)malloc(32); 11 strcpy(hello1, "hello world"); 12 hello2 = (char *)malloc(strlen(hello1)+1); 13 strcpy(hello2, hello1); 14 } 15 16 void 17 memory_leak() 18 { 19 char *local; 20 local = (char *)malloc(32); 21 strcpy(local, "hello world"); 22 } 23 24 void 25 access_error() 26 { 27 int i,j; 28 29 i = j; 30 } 31 32 int 33 main() 34 { 35 memory_use(); 36 access_error(); 37 memory_leak(); 38 printf("%s\n", hello2); 39 return 0; 40 } % cc -g -o hello hello.c % dbx -C hello ld.so.1 の読み込み中 librtc.so のシンボル情報を読んでいます libw.so.1 の読み込み中 libdl.so.1 の読み込み中 (dbx) check -access アクセス検査 - ON (dbx) check -memuse メモリー使用状況検査 - ON (dbx) run Running: hello (プロセス id 18306) 実行時検査を有効にしています...done 非初期化領域からの読み取り (rui): 4 バイト読み取りをアドレス 0xeffff068 でしようとしました それは 96 バイト現スタックポインタより上です 変数は 'j' です。 現関数: access_error 29 i = j; (dbx) cont hello world メモリーリーク検査中... 実際のリークの報告 (実際のリーク: 1 合計サイズ: 32 バイト) 合計 ブロック リーク 割り当て呼び出しスタック サイズ 数 ブロック アドレス ========== ====== ========== ======================================= 32 1 0x21aa8 memory_leak < main 起こり得るリークの報告 (起こり得るリーク: 0 合計サイズ: 0 バイト) メモリー使用状況検査中... ブロック使用量の報告 (ブロック使用量: 2 合計サイズ: 44 バイト 合計 割合 ブロック 平均 割り当て呼び出しスタック サイズ % 数 サイズ ========== ==== ====== ====== ======================================= 32 72% 1 32 memory_use < main 12 27% 1 12 memory_use < main 実行完了。終了コードは 0 です。 |
関数 access_error() は、初期化される前の変数 j を読み取ります。RTC は、このアクセスエラーを非初期化領域からの読み取り (rui) として報告します。
関数 memory_leak() は、終了する前に local を解放 (free()) しません。memory_leak() が終了してしまうと、local がスコープ外になり、行 20 で確保したブロックがリークになります。
プログラムは、常にスコープ内にある大域変数 hello1 と hello2 を使用します。これらの変数はいずれも、使用中ブロック (biu) として報告される割り当て済みメモリーを動的に指します。