Debugging a Program With dbx

Using RTC

To use runtime checking, enable the type of checking you want to use.

To turn on the desired checking mode, start dbx with the -C option:


% dbx [-C] program_name

The -C flag forces early loading of the RTC library. When you start dbx without the -C option and then enable checking, the RTC library is loaded when you issue the next run command; that may cause reloading of the shared libraries needed by the program. Using the -C flag initially allows you to avoid reloading.


Note -

You must turn on the type of checking you want before you run the program.


To turn on memory use and memory leak checking:


(dbx) check -memuse

To turn on memory access checking only:


(dbx) check -access

To turn on memory leak, memory use, and memory access checking:


(dbx) check -all

To turn off RTC entirely:


(dbx) uncheck -all

Run the program being tested, with or without breakpoints.

The program runs normally, but slowly because each memory access is checked for validity just before it occurs. If dbx detects invalid access, it displays the type and location of the error. Control returns to you (unless the dbxenv variable rtc_auto_continue is set to on). You can then issue dbx commands, such as where to get the current stack trace or print to examine variables. If the error is not a fatal error, you can continue execution of the program with the cont command. The program continues to the next error or breakpoint, whichever is detected first.

If rtc_auto_continue is set to on, RTC continues to find errors, and keeps running automatically. It redirects errors to the value of the dbxenv variable rtc_error_log_file_name.

You can limit the reporting of RTC errors using the suppress command. The program continues to the next error or breakpoint, whichever is detected first.

You can perform any of the usual debugging activities, such as setting breakpoints and examining variables. The cont command runs the program until another error or breakpoint is encountered or until the program terminates.

Below is a simple example showing how to turn on memory access and memory use checking for a program called 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
Reading symbolic information for hello
Reading symbolic information for rtld /usr/lib/ld.so.1
Reading symbolic information for librtc.so
Reading symbolic information for libc.so.1
Reading symbolic information for libdl.so.1
(dbx) check -access   
access checking - ON
(dbx) check -memuse
memuse checking - ON
(dbx) run         
Running: hello 
(process id 18306)
Enabling Error Checking... done
Read from uninitialized (rui):
Attempting to read 4 bytes at address 0xeffff068
    which is 96 bytes above the current stack pointer
Variable is 'j'
Current function is access_error
   29       i = j;
(dbx) cont
hello world
Checking for memory leaks...
Actual leaks report    (actual leaks:         1 total size:      32 bytes)

 Total  Num of  Leaked      Allocation call stack
 Size   Blocks  Block
                Address
======  ====== ==========  =======================================
    32       1    0x21aa8  memory_leak < main 

Possible leaks report  (possible leaks:       0  total size:      0 bytes)

Checking for memory use...
Blocks in use report   (blocks in use:        2  total size:      44 bytes)

 Total  % of Num of  Avg     Allocation call stack
 Size    All Blocks  Size
======= ==== ====== ======  =======================================
     32  72%      1     32  memory_use < main 
     12  27%      1     12  memory_use < main 

execution completed, exit code is 0

The function access_error() reads variable j before it is initialized. RTC reports this access error as a Read from uninitialized (rui).

Function memory_leak() does not free() the variable local before it returns. When memory_leak() returns, this variable goes out of scope and the block allocated at line 20 becomes a leak.

The program uses global variables hello1 and hello2, which are in scope all the time. They both point to dynamically allocated memory, which is reported as Blocks in use (biu).