[ Bottom of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]

General Programming Concepts:
Writing and Debugging Programs

Examining Program Data

This section explains how to examine, test, and modify program data.

Handling Signals

The dbx debug program can either trap or ignore signals before they are sent to your program. Each time your program is to receive a signal, the dbx program is notified. If the signal is to be ignored, it is passed to your program; otherwise, the dbx program stops the program and notifies you that a signal has been trapped. The dbx program cannot ignore the SIGTRAP signal if it comes from a process outside of the debug process. In a multi-threaded program, a signal can be sent to a particular thread via the pthread_kill subroutine. By default, the dbx program stops and notifies you that a signal has been trapped. If you request a signal be passed on to your program using the ignore subcommand, the dbx program ignores the signal and passes it on to the thread. Use the catch and ignore subcommands to change the default handling.

In the following example, a program uses SIGGRANT and SIGREQUEST to handle allocation of resources. In order for the dbx program to continue each time one of these signals is received, enter:

(dbx) ignore GRANT
(dbx) ignore SIGREQUEST
(dbx) ignore
CONT CLD ALARM KILL GRANT REQUEST

The dbx debug program can block signals to your program if you set the $sigblock variable. By default, signals received through the dbx program are sent to the source program or the object file specified by the dbx ObjectFile parameter. If the $sigblock variable is set using the set subcommand, signals received by the dbx program are not passed to the source program. If you want a signal to be sent to the program, use the cont subcommand and supply the signal as an operand.

You can use this feature to interrupt execution of a program running under the dbx debug program. Program status can be examined before continuing execution as usual. If the $sigblock variable is not set, interrupting execution causes a SIGINT signal to be sent to the program. This causes execution, when continued, to branch to a signal handler if one exists.

The following example program illustrates how execution using the dbx debug program changes when the $sigblock variable is set:

#include <signal.h>
#include <stdio.h>
void inthand( ) {
        printf("\nSIGINT received\n");
        exit(0);
}

main( )
{
        signal(SIGINT, inthand);
        while (1) {
                  printf(".");
                  fflush(stdout);
                sleep(1);
        }
}

The following sample session with the dbx program uses the preceding program as the source file. In the first run of the program, the $sigblock variable is not set. During rerun, the $sigblock variable is set. Comments are placed between angle brackets to the right:

dbx version 3.1.
Type 'help' for help.
reading symbolic information ...
(dbx) run
.........^C                      <User pressed Ctrl-C here!>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014         1        r2,0x14(r1)
(dbx) cont

SIGINT received

execution completed
(dbx) set $sigblock
(dbx) rerun
[ looper ]
..............^C                  <User pressed Ctrl-C here!>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014          1        r2,0x14(r1)
(dbx) cont
....^C   <Program did not receive signal, execution continued>

interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014          1         r2,0x14(r1)
(dbx) cont 2                     <End program with a signal 2>

SIGINT received

execution completed
(dbx)

Calling Procedures

You can call your program procedures from the dbx program to test different arguments. You can also call diagnostic routines that format data to aid in debugging. Use the call subcommand or the print subcommand to call a procedure.

Displaying a Stack Trace

To list the procedure calls preceding a program halt, use the where command.

In the following example, the executable object file, hello, consists of two source files and three procedures, including the standard procedure main. The program stopped at a breakpoint in procedure sub2.

(dbx) run
[1] stopped in sub2 at line 4 in file "hellosub.c"
(dbx) where
sub2(s = "hello", n = 52), line 4 in "hellosub.c"
sub(s = "hello", a = -1, k = delete), line 31 in "hello.c"
main(), line 19 in "hello.c"

The stack trace shows the calls in reverse order. Starting at the bottom, the following events occurred:

  1. Shell called main.
  2. main called sub procedure at line 19 with values s = "hello", a = -1, and k = delete.
  3. sub called sub2 procedure at line 31 with values s = "hello" and n = 52.
  4. The program stopped in sub2 procedure at line 4.

    Note: Set the debug program variable $noargs to turn off the display of arguments passed to procedures.

You can also display portions of the stack with the up and down subcommands.

Displaying and Modifying Variables

To display an expression, use the print subcommand. To print the names and values of variables, use the dump subcommand. If the given procedure is a period, then all active variables are printed. To modify the value of a variable, use the assign subcommand.

In the following example, a C program has an automatic integer variable x with value 7, and s and n parameters in the sub2 procedure:

(dbx) print x, n
7 52
(dbx) assign x = 3*x
(dbx) print x
21
(dbx) dump
sub2(s = "hello", n = 52)
x = 21

Displaying Thread-Related Information

To display information on user threads, mutexes, conditions, and attribute objects, use the thread, mutex, condition, and attribute subcommands. You can also use the print subcommand on these objects. In the following example, the running thread is thread 1. The user sets the current thread to be thread 2, lists the threads, prints information on thread 1, and finally prints information on several thread-related objects.

(dbx) thread current 2
(dbx) thread
 thread  state-k   wchan state-u   k-tid mode held scope function
*$t1     run             running   12755   u   no   pro  main
>$t2     run             running   12501   k   no   sys  thread_1
(dbx) print $t1
(thread_id = 0x1, state = run, state_u = 0x0, tid = 0x31d3, mode = 0x1, held = 0x0, priority = 0x3c,
    policy = other, scount = 0x1, cursig = 0x5, attributes = 0x200050f8)

(dbx) print $a1,$c1,$m2
(attr_id = 0x1, type = 0x1, state = 0x1, stacksize = 0x0, detachedstate = 0x0, process_shared = 0x0,
 contentionscope = 0x0, priority = 0x0, sched = 0x0, inherit = 0x0, protocol = 0x0, prio_ceiling = 0x0)
(cv_id = 0x1, lock = 0x0, semaphore_queue = 0x200032a0, attributes = 0x20003628)
(mutex_id = 0x2, islock = 0x0, owner = (nil), flags = 0x1, attributes = 0x200035c8)

Scoping of Names

Names resolve first using the static scope of the current function. The dynamic scope is used if the name is not defined in the first scope. If static and dynamic searches do not yield a result, an arbitrary symbol is chosen and the message using QualifiedName is printed. You can override the name resolution procedure by qualifying an identifier with a block name (such as Module.Variable). Source files are treated as modules named by the file name without the suffix. For example, the x variable, which is declared in the sub procedure inside the hello.c file, has the fully qualified name hello.sub.x. The program itself has a period for a name.

The which and whereis subcommands can be helpful in determining which symbol is found when multiple symbols with the same name exist.

Using Operators and Modifiers in Expressions

The dbx program can display a wide range of expressions. Specify expressions with a common subset of C and Pascal syntax, with some FORTRAN extensions.

* (asterisk) or ^ (caret) Denotes indirection or pointer dereferencing.
[ ] (brackets) or ( ) (parentheses) Denotes subscript array expressions.
. (period) Use this field reference operator with pointers and structures. This makes the C operator -> (arrow) unnecessary, although it is allowed.
& (ampersand) Gets the address of a variable.
.. (two periods) Separates the upper and lower bounds when specifying a subsection of an array. For example: n[1..4].

The following types of operations are valid in expressions:

Algebraic =, -, *,/(floating division), div (integral division), mod, exp (exponentiation)
Bitwise -, I, bitand, xor, ~, <<, >>
Logical or, and, not, II, &&
Comparison <, >, <=, >=, <> or !=, = or ==
Other sizeof

Logical and comparison expressions are allowed as conditions in stop and trace subcommands.

Checking of Expression Types

The dbx debug program checks expression types. You can override the expression type by using a renaming or casting operator. There are three forms of type renaming:

Note: When you cast to or from a structure, union, or class, the casting is left-justified. However, when casting from a class to a base class, C++ syntax rules are followed.

For example, to rename the x variable where x is an integer with a value of 97, enter:

(dbx) print char (x), x \ char, (char) x, x,
'a' 'a' 'a' 97

The following examples show how you can use the (Typename) Expression form of type renaming:

print (float) i

print ((struct qq *) void_pointer)->first_element

The following restrictions apply to C-style typecasting for the dbx debug program:

The whatis subcommand prints the declaration of an identifier, which you can then qualify with block names.

Use the $$TagName construct to print the declaration of an enumeration, structure, or union tag (or the equivalent in Pascal).

The type of the assign subcommand expression must match the variable type you assigned. If the types do not match, an error message is displayed. Change the expression type using a type renaming. Disable type checking by setting a special dbx debug program $unsafeassign variable.

Folding Variables to Lowercase and Uppercase

By default, the dbx program folds symbols based on the current language. If the current language is C, C++, or undefined, the symbols are not folded. If the current language is FORTRAN or Pascal, the symbols are folded to lowercase. The current language is undefined if the program is in a section of code that has not been compiled with the debug flag. You can override default handling with the case subcommand.

Using the case subcommand without arguments displays the current case mode.

The FORTRAN and Pascal compilers convert all program symbols to lowercase; the C compiler does not.

Changing Print Output with Special Debug Program Variables

Use the set subcommand to set the following special dbx debug program variables to get different results from the print subcommand:

$hexints Prints integer expressions in hexadecimal.
$hexchars Prints character expressions in hexadecimal.
$hexstrings Prints the address of the character string, not the string itself.
$octints Prints integer expressions in octal.
$expandunions Prints fields within a union.
$pretty Displays complex C and C++ types in pretty format.

Set and unset the debug program variables to get the desired results. For example:

(dbx) whatis x; whatis i; whatis s
int x;
char i;
char *s;
(dbx) print x, i, s
375 'c' "hello"
(dbx) set $hexstrings; set $hexints; set $hexchars
(dbx) print x, i, s
0x177 0x63 0x3fffe460
(dbx) unset $hexchars; set $octints
(dbx) print x, i
0567 'c'
(dbx) whatis p
struct info p;
(dbx) whatis struct info
struct info {
    int x;
    double position[3];
    unsigned char c;
    struct vector force;
};
(dbx) whatis struct vector
struct vector {
    int a;
    int b;
    int c;
};
(dbx) print p
(x = 4, position = (1.3262493258532527e-315, 0.0, 0.0), c = '\0', force = (a = 0, b = 9, c = 1))
(dbx) set $pretty="on"
(dbx) print p
{
    x = 4
    position[0] = 1.3262493258532527e-315
    position[1] = 0.0
    position[2] = 0.0
    c = '\0'
    force = {
        a = 0
        b = 9
        c = 1
    }
}
(dbx) set $pretty="verbose"
(dbx) print p
x = 4
position[0] = 1.3262493258532527e-315
position[1] = 0.0
position[2] = 0.0
c = '\0'
force.a = 0
force.b = 9
force.c = 1

[ Top of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]