Sun Studio 12: Debugging a Program With dbx

Chapter 8 Evaluating and Displaying Data

In dbx, you can perform two types of data checking:

This chapter is organized into the following sections:

Evaluating Variables and Expressions

This section discusses how to use dbx to evaluate variables and expressions.

Verifying Which Variable dbx Uses

If you are not sure which variable dbx is evaluating, use the which command to see the fully qualified name dbx is using.

To see other functions and files in which a variable name is defined, use the whereis command.

For information on the commands, see which Command and whereis Command.

Variables Outside the Scope of the Current Function

When you want to evaluate or monitor a variable outside the scope of the current function:

Printing the Value of a Variable, Expression, or Identifier

An expression should follow current language syntax, with the exception of the meta syntax that dbx introduces to deal with scope and arrays.

To evaluate a variable or expression in native code, type:


print expression

You can use the print command to evaluate an expression, local variable, or parameter in Java code.

For more information, see print Command.


Note –

dbx supports the C++ dynamic_cast and typeid operators. When evaluating expressions with these two operators, dbx makes calls to certain rtti functions made available by the compiler. If the source doesn’t explicitly use the operators, those functions might not have been generated by the compiler, and dbx fails to evaluate the expression.


Using Pretty-Printing

Pretty-printing lets your program provide its own rendition of an expression's value through a function call. If you specify the -p option to the print command, rprint command, display command, or watch command, dbx searches for a function of the form const chars *db_pretty_print(const T *, int flags, const char *fmt) and calls it, substituting the returned value for print or display.

The value passed in the flags argument of the function is bit-wise or one of the following:

FVERBOSE

0x1

Not currently implemented, always set 

FDYNAMIC

0x2

-d

FRECURSE

0x4

-r

FFORMAT

0x8

-f (if set, fmt is the format part)

FLITERAL

0x10

-l

The db_pretty_print() function can be either a static member function or a standalone function.

If the dbx environment variable output_pretty_print is set to on, -p is passed to the print command, rprint command, or display command as the default. Use +p to override this behavior.

Consider also the following:

Printing C++

In C++ an object pointer has two types, its static type (what is defined in the source code) and its dynamic type (what an object was before any casts were made to it). dbx can sometimes provide you with the information about the dynamic type of an object.

In general, when an object has a virtual function table (a vtable) in it, dbx can use the information in the vtable to correctly determine an object’s type.

You can use the print command, display command, or watch command with the -r (recursive) option. dbx displays all the data members directly defined by a class and those inherited from a base class.

These commands also take a -d or +d option that toggles the default behavior of the dbx environment variable output_derived_type.

Using the -d flag or setting the dbx environment variable output_dynamic_type to on when there is no process running generates a “program is not active” error message because it is not possible to access dynamic information when there is no process. An “illegal cast on class pointers” error message is generated if you try to find a dynamic type through a virtual inheritance. (Casting from a virtual base class to a derived class is not legal in C++.)

Evaluating Unnamed Arguments in C++ Programs

C++ lets you define functions with unnamed arguments. For example:


void tester(int)
{
};
main(int, char **)
{
   tester(1);
};

Though you cannot use unnamed arguments elsewhere in a program, the compiler encodes unnamed arguments in a form that lets you evaluate them. The form is as follows, where the compiler assigns an integer to %n:


_ARG%n

To obtain the name assigned by the compiler, type the whatis command with the function name as its target.


(dbx) whatis tester
void tester(int _ARG1);
(dbx) whatis main
int main(int _ARG1, char **_ARG2);

For more information, see whatis Command.

To evaluate (or display) an unnamed function argument, type:


(dbx) print _ARG1
_ARG1 = 4

Dereferencing Pointers

When you dereference a pointer, you ask for the contents of the container to which the pointer points.

To dereference a pointer, dbx displays the evaluation in the command pane; in this case, the value pointed to by t:


(dbx) print *t
*t = {
a = 4
}

Monitoring Expressions

Monitoring the value of an expression each time the program stops is an effective technique for learning how and when a particular expression or variable changes. The display command instructs dbx to monitor one or more specified expressions or variables. Monitoring continues until you turn it off with the undisplay command.

To display the value of a variable or expression each time the program stops, type:


display expression, ...

You can monitor more than one variable at a time. The display command used with no options prints a list of all expressions being displayed.

For more information, see display Command.

Turning Off Display (Undisplaying)

dbx continues to display the value of a variable you are monitoring until you turn off display with the undisplay command. You can turn off the display of a specified expression or turn off the display of all expressions currently being monitored.

To turn off the display of a particular variable or expression, type:


undisplay expression

To turn off the display of all currently monitored variables, type:


undisplay 0

For more information, see undisplay Command.

Assigning a Value to a Variable

To assign a value to a variable, type:


assign variable = expression

Evaluating Arrays

You evaluate arrays the same way you evaluate other types of variables.

Here is a sample Fortran array:


integer*4 arr(1:6, 4:7)

To evaluate the array, use the print command. For example:


(dbx) print arr(2,4)

The dbx print command lets you evaluate part of a large array. Array evaluation includes:

You can slice an array, with or without striding. (The default stride value is 1, which means print each element.)

Array Slicing

Array slicing is supported in the print, display, and watch commands for C, C++, and Fortran.

Array Slicing Syntax for C and C++

For each dimension of an array, the full syntax of the print command to slice the array is:


print array-expression [first-expression .. last-expression : stride-expression]

where:

array-expression

Expression that should evaluate to an array or pointer type.

first-expression

First element to be printed. Defaults to 0.

last-expression

Last element to be printed. Defaults to upper bound.

stride-expression

Length of the stride (the number of elements skipped is stride-expression-1). Defaults to 1.

The first expression, last expression, and stride expression are optional expressions that should evaluate to integers.

For example:


(dbx) print arr[2..4]
arr[2..4] =
[2] = 2
[3] = 3
[4] = 4
(dbx) print arr[..2]
arr[0..2] =
[0] = 0
[1] = 1
[2] = 2

(dbx) print arr[2..6:2]
arr[2..6:2] =
[2] = 2
[4] = 4
[6] = 6

Array Slicing Syntax for Fortran

For each dimension of an array, the full syntax of the print command to slice the array is:


print array-expression [first-expression : last-expression : stride-expression]

where:

array-expression

Expression that should evaluate to an array type.

first-expression

First element in a range, also first element to be printed. Defaults to lower bound.

last-expression

Last element in a range, but might not be the last element to be printed if stride is not equal to 1. Defaults to upper bound.

stride-expression

Length of the stride. Defaults to 1.

The first expression, last expression, and stride expression are optional expressions that should evaluate to integers. For an n-dimensional slice, separate the definition of each slice with a comma.

For example:


(dbx) print arr(2:6)
arr(2:6) =
(2) 2
(3) 3
(4) 4
(5) 5
(6) 6

(dbx) print arr(2:6:2)
arr(2:6:2) =
(2) 2
(4) 4
(6) 6

To specify rows and columns, type:


demo% f95 -g -silent ShoSli.f
demo% dbx a.out
Reading symbolic information for a.out
(dbx) list 1,12
    1         INTEGER*4 a(3,4), col, row
    2         DO row = 1,3
    3             DO col = 1,4
    4               a(row,col) = (row*10) + col
    5             END DO
    6         END DO
    7         DO row = 1, 3
    8                WRITE(*,’(4I3)’) (a(row,col),col=1,4)
    9        END DO
    10        END
(dbx) stop at 7
(1) stop at "ShoSli.f":7
(dbx) run
Running: a.out
stopped in MAIN at line 7 in file "ShoSli.f"
    7          DO row = 1, 3

To print row 3, type:


(dbx) print a(3:3,1:4)
’ShoSli’MAIN’a(3:3, 1:4) =
        (3,1)   31
        (3,2)   32
        (3,3)   33
        (3,4)   34
(dbx)

To print column 4, type:


(dbx) print a(1:3,4:4)
’ShoSli’MAIN’a(1:3, 1:4) =
        (1,4)   14
        (2,4)   24
        (3,4)   34
(dbx)

Slices

Here is an example of a two-dimensional, rectangular slice of a C++ array, with the default stride of 1 omitted.


print arr(201:203, 101:105)

This command prints a block of elements in a large array. Note that the command omits stride-expression, using the default stride value of 1.

Diagram of an array with columns 100 through 106 and
rows 200 through 205. Elements in columns 101 through 105 of rows 201 through
203 are shaded.

As illustrated, the first two expressions (201:203) specify a slice in the first dimension of this two-dimensional array (the three-row column). The slice starts with row 201 and ends with 203. The second set of expressions, separated by a comma from the first, defines the slice for the second dimension. The slice begins with column 101 and ends with column 105.

Strides

When you instruct print to stride across a slice of an array, dbx evaluates certain elements in the slice only, skipping over a fixed number of elements between each one it evaluates.

The third expression in the array slicing syntax, stride-expression, specifies the length of the stride. The value of stride-expression specifies the elements to print. The default stride value is 1, meaning: evaluate all of the elements in the specified slices.

Here is the same array used in the previous example of a slice. This time the print command includes a stride of 2 for the slice in the second dimension.


print arr(201:203, 101:105:2)

As shown in the diagram, a stride of 2 prints every second element, skipping every other element.

Diagram of an array with columns 100 through 106 and
rows 200 through 205. Elements in columns 101, 103, and 105 of rows 201 through
203 are shaded.

For any expression you omit, print takes a default value equal to the declared size of the array. Here are examples showing how to use the shorthand syntax.

For a one-dimensional array, use the following commands:

print arr

Prints the entire array with default boundaries.

print arr(:)

Prints the entire array with default boundaries and default stride of 1.

print arr(::stride-expression)

Prints the entire array with a stride of stride-expression.

For a two-dimensional array, the following command prints the entire array.


print arr

To print every third element in the second dimension of a two-dimensional array, type:


print arr (:,::3)