dbx コマンドによるデバッグ

RTC の使用

実行時検査を使用するには、使用したい検査の種類を指定します。

必要な検査モードを有効にするには、-C オプションを付けて dbx を起動します。


% dbx -C program_name

-C フラグは、RTC ライブラリの初期読み込みを強制的に実行するものです。dbx-C オプションを付けずに起動して、検査を有効にした場合、RTC ライブラリは、次に run コマンドを発行したときに読み込まれます。これにより、プログラムで必要な共有ライブラリが再読み込みされる可能性があります。-C フラグを使用すると、この再読み込みを避けることができます。


注 -

必要な検査の種類を指定してから、プログラムを実行するようにしてください。


メモリーの使用状況およびメモリーリークの検査をオンにするには、次のように入力します。


(dbx) check -memuse

メモリーアクセス検査だけをオンにするには、次のように入力します。


(dbx) check -access

メモリーリーク、メモリー使用状況、およびメモリーアクセスの各検査をオンにするには、次のように入力します。


(dbx) check -all

RTC 全体をオフにするには、次のように入力します。


(dbx) uncheck -all

検査したいプログラムを実行してください。ブレークポイントは同時に使用できます。

プログラムは正常に実行されますが、処理速度は遅くなります。これは、メモリーアクセスが起こる直前ごとに妥当性が検査されるためです。dbx は、無効なアクセスを検出すると、エラーのタイプと位置を表示します。dbxenvrtc_auto_continueon に設定されていない限り、制御はユーザーに返されます。ここで、現在のスタックトレースを表示するための where や、変数を調べるための print などの dbx コマンドを実行できます。エラーが重大エラーでなければ、cont コマンドによってプログラムを実行し続けることができます。プログラムは、次のエラーまたはブレークポイントのいずれかが検出されるまで続行されます。

rtc_auto_continueon に設定されている場合、RTC はエラーを検出し、自動的に実行し続けます。dbxenvrtc_error_log_file_name が設定されている場合には、結果はそのファイルにリダイレクトされます。

suppress コマンドを使用すると、RTC エラーの報告を制限することができます。プログラムは、次のエラーまたはブレークポイントのいずれかが検出されるまで続けられます。

ブレークポイントの設定や変数の検査など、通常のデバッグ動作をすべて実行することができます。cont コマンドは、別のエラーまたはブレークポイントが見つかるまで、あるいはプログラムが終了するまでプログラムを実行し続けます。

次の例は、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
hello のシンボル情報を読んでいます
rtld /usr/lib/ld.so.1 のシンボル情報を読んでいます
librtc.so のシンボル情報を読んでいます
libc.so.1 のシンボル情報を読んでいます
libdl.so.1 のシンボル情報を読んでいます
(dbx) check -access
アクセス検査 - ON
(dbx) check -memuse
メモリー使用状況検査 - ON
(dbx) run
実行中: hello 
(プロセス id 18306)
実行時検査を有効にしています...終了
非初期化領域からの読み取り (rui):
4 バイト読み取り を アドレス 0xeffff068 で しようとしました
    それは 96 バイト 現スタックポインタより上 です
変数は 'j' です。
現関数 :access_error
   29           i = j;
(dbx) cont

メモリーリーク検査中...

実際のリークの報告       (実際のリーク:         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 で確保したブロックがリークになります。

プログラムは、常にスコープ内にある大域変数 hello1hello2 を使用します。これらの変数はいずれも、使用中ブロック (biu) として報告される割り当て済みメモリーを動的に指します。