The topics below describe how to use Debug Tool to debug your C and C++ programs.
Example: referencing variables and setting breakpoints in C and C++ blocks
Refer to the following topics for more information related to the material discussed in this topic.
Debug Tool’s command language is a subset of C and C++ commands and has the same syntactical requirements. Debug Tool allows you to work in a language you are familiar with so learning a new set of commands is not necessary.
The table below shows the interpretive subset of C and C++ commands recognized by Debug Tool.
| Command | Description |
|---|---|
| block ({}) | Composite command grouping |
| break | Termination of loops or switch commands |
| declarations | Declaration of session variables |
| do/while | Iterative looping |
| expression | Any C expression except the conditional (?) operator |
| for | Iterative looping |
| if | Conditional execution |
| switch | Conditional execution |
This subset of commands is valid only when the current programming language is C or C++.
In addition to the subset of C and C++ commands that you can use is a list of reserved keywords used and recognized by C and C++ that you cannot abbreviate, use as variable names, or use as any other type of identifier.
Refer to the following topics for more information related to the material discussed in this topic.
Debug Tool can process all program variables that are valid in C or C++. You can assign and display the values of variables during your session. You can also declare session variables with the recognized C declarations to suit your testing needs.
Refer to the following topics for more information related to the material discussed in this topic.
Debug Tool obtains information about a program variable by name using the symbol table built by the compiler. If you specify TEST(SYM) at compile time, the compiler builds a symbol table that allows you to reference any variable in the program.
Refer to the following topics for more information related to the material discussed in this topic.
To display the values of variables or expressions, use the LIST command. The LIST command causes Debug Tool to log and display the current values (and names, if requested) of variables, including the evaluated results of expressions.
Suppose you want to display the program variables X, row[X], and col[X], and their values at line 25. If you issue the following command:
AT 25 LIST ( X, row[X], col[X] ); GO;
Debug Tool sets a breakpoint at line 25 (AT), begins execution of the program (GO), stops at line 25, and displays the variable names and their values.
If you want to see the result of their addition, enter:
AT 25 LIST ( X + row[X] + col[X] ); GO;
Debug Tool sets a breakpoint at line 25 (AT), begins execution of the program (GO), stops at line 25, and displays the result of the expression.
Put commas between the variables when listing more than one. If you do not want to display the variable names when issuing the LIST command, enter LIST UNTITLED.
You can also list variables with the printf function call as follows:
printf ("X=%d, row=%d, col=%d\n", X, row[X], col[X]);The output from printf, however, does not appear in the Log window and is not recorded in the log file unless you SET INTERCEPT ON FILE stdout.
To assign a value to a C and C++ variable, you use an assignment expression. Assignment expressions assign a value to the left operand. The left operand must be a modifiable lvalue. An lvalue is an expression representing a data object that can be examined and altered.
C contains two types of assignment operators: simple and compound. A simple assignment operator gives the value of the right operand to the left operand.
The following example demonstrates how to assign the value of number to the member employee of the structure payroll:
payroll.employee = number;
Compound assignment operators perform an operation on both operands and give the result of that operation to the left operand. For example, this expression gives the value of index plus 2 to the variable index:
index += 2
Debug Tool supports all C operators except the tenary operator, as well as any other full C language assignments and function calls to user or C library functions.
Refer to the following topics for more information related to the material discussed in this topic.
The table below shows the possible values for the Debug Tool variable %PATHCODE when the current programming language is C and C++.
| -1 | Debug Tool is not in control as the result of a path or attention situation. |
| 0 | Attention function (not ATTENTION condition). |
| 1 | A block has been entered. |
| 2 | A block is about to be exited. |
| 3 | Control has reached a user label. |
| 4 | Control is being transferred as a result of a function reference. The invoked routine’s parameters, if any, have been prepared. |
| 5 | Control is returning from a function reference. Any return code contained in register 15 has not yet been stored. |
| 6 | Some logic contained by a conditional do/while, for, or while statement is about to be executed. This can be a single or Null statement and not a block statement. |
| 7 | The logic following an if(...) is about to be executed. |
| 8 | The logic following an else is about to be executed. |
| 9 | The logic following a case within an switch is about to be executed. |
| 10 | The logic following a default within a switch is about to be executed. |
| 13 | The logic following the end of a switch, do, while, if(...), or for is about to be executed. |
| 17 | A goto, break, continue, or return is about to be executed. |
Values in the range 3-17 can only be assigned to %PATHCODE if your program was compiled with an option supporting path hooks.
You might want to declare session variables for use during the course of your session. You cannot initialize session variables in declarations. However, you can use an assignment statement or function call to initialize a session variable.
As in C, keywords can be specified in any order. Variable names up to 255 characters in length can be used. Identifiers are case-sensitive, but if you want to use the session variable when the current programming language changes from C to another HLL, the variable must have an uppercase name and compatible attributes.
To declare a hexadecimal floating-point variable called maximum, enter the following C declaration:
double maximum;
You can only declare scalars, arrays of scalars, structures, and unions in Debug Tool (pointers for the above are allowed as well).
If you declare a session variable with the same name as a programming variable, the session variable hides the programming variable. To reference the programming variable, you must qualify it. For example:
main:>x for the program variable x x for the session variable x
Session variables remain in effect for the entire debug session, unless they are cleared using the CLEAR command.
Refer to the following topics for more information related to the material discussed in this topic.
Debug Tool allows evaluation of expressions in your test program. All expressions available in C and C++ are also available within Debug Tool except for the conditional expression (? :). That is, all operators such as +, -, %:, and += are fully supported with the exception of the conditional operator.
C and C++ language expressions are arranged in the following groups based on the operators they contain and how you use them:
An lvalue is an expression representing a data object that can be examined and altered. For a more detailed description of expressions and operators, see the C and C++ Program Guides.
The semantics for C and C++ operators are the same as in a compiled C or C++ program. Operands can be a mixture of constants (integer, floating-point, character, string, and enumeration), C and C++ variables, Debug Tool variables, or session variables declared during a Debug Tool session. Language constants are specified as described in the C and C++ Language Reference publications.
The Debug Tool command DESCRIBE ATTRIBUTES can be used to display the resultant type of an expression, without actually evaluating the expression.
The C and C++ language does not specify the order of evaluation for function call arguments. Consequently, it is possible for an expression to have a different execution sequence in compiled code than within Debug Tool. For example, if you enter the following in an interactive session:
int x;
int y;
x = y = 1;
printf ("%d %d %d%" x, y, x=y=0);the results can differ from results produced by the same statements located in a C or C++ program segment. Any expression containing behavior undefined by ANSI standards can produce different results when evaluated by Debug Tool than when evaluated by the compiler.
The following examples show you various ways Debug Tool supports the use of expressions in your programs:
a = (1,2/3,a++,b++,printf("hello world\n"));league[num].team[1].player[1]++; league[num].team[1].total += 1; ++(*pleague);
v.x = 3; a = b = c = d = 0; *(pointer++) -= 1;
*pointer_to_long = 3521L = 0x69a1; float_val = 3e-11 + 6.6E-10; char_val = '7';
intensity <<= 1, shade * increment, rotate(direction); alpha = (y>>3, omega % 4);
long_double_val = unsigned_short_val; long_double_val = (long double) 3;
Refer to the following topics for more information related to the material discussed in this topic.
You can perform calls to user and C library functions within Debug Tool, unless your program was compiled with the FORMAT(DWARF) suboption of the DEBUG compiler option.
You can make calls to C library functions at any time. In addition, you can use the C library variables stdin, stdout, stderr, __amrc, and errno in expressions including function calls.
The library function ctdli cannot be called unless it is referenced in a compile unit in the program, either main or a function linked to main.
Calls to user functions can be made, provided Debug Tool is able to locate an appropriate definition for the function within the symbol information in the user program. These definitions are created when the program is compiled with TEST(SYM) for C or TEST for C++.
Debug Tool performs parameter conversions and parameter-mismatch checking where possible. Parameter checking is performed if:
You can turn off this checking by specifying SET WARNING OFF.
Calls can be made to any user functions that have linkage supported by the C or C++ compiler. However, for C++ calls made to any user function, the function must be declared as:
extern "C"
For example, use this declaration if you want to debug an application signal handler. When a condition occurs, control passes to Debug Tool which then passes control to the signal handler.
Debug Tool attempts linkage checking, and does not perform the function call if it determines there is a linkage mismatch. A linkage mismatch occurs when the target program has one linkage but the source program believes it has a different linkage.
It is important to note the following regarding function calls:
Refer to the following topics for more information related to the material discussed in this topic.
The table below lists all keywords reserved by the C language. When the current programming language is C or C++, these keywords cannot be abbreviated, used as variable names, or used as any other type of identifiers.
| auto | else | long | switch |
| break | enum | register | typedef |
| case | extern | return | union |
| char | float | short | unsigned |
| const | for | signed | void |
| continue | goto | sizeof | volatile |
| default | if | static | while |
| do | int | struct | _Packed |
| double |
The table below lists the C language operators in order of precedence and shows the direction of associativity for each operator. The primary operators have the highest precedence. The comma operator has the lowest precedence. Operators in the same group have the same precedence.
| Precedence level | Associativity | Operators |
|---|---|---|
| Primary | left to right | () [ ] . -> |
| Unary | right to left | ++ -- - + ! ~ & * (typename) sizeof |
| Multiplicative | left to right | * / % |
| Additive | left to right | + - |
| Bitwise shift | left to right | << >> |
| Relational | left to right | < > <= >= |
| Equality | left to right | ++ != |
| Bitwise logical AND | left to right | & |
| Bitwise exclusive OR | left to right | ^ or ¬ |
| Bitwise inclusive OR | left to right | | |
| Logical AND | left to right | && |
| Logical OR | left to right | || |
| Assignment | right to left | = += -= *= /= <<= >>= %= &= ^= |= |
| Comma | left to right | , |
Language Environment condition names (the symbolic feedback codes CEExxx) can be used interchangeably with the equivalent C and C++ conditions listed in the following table. For example, AT OCCURRENCE CEE341 is equivalent to AT OCCURRENCE SIGILL. Raising a CEE341 condition triggers an AT OCCURRENCE SIGILL breakpoint and vice versa.
| Language Environment condition | Description | Equivalent C/C++ condition |
|---|---|---|
| CEE341 | Operation exception | SIGILL |
| CEE342 | Privileged operation exception | SIGILL |
| CEE343 | Execute exception | SIGILL |
| CEE344 | Protection exception | SIGSEGV |
| CEE345 | Addressing exception | SIGSEGV |
| CEE346 | Specification exception | SIGILL |
| CEE347 | Data exception | SIGFPE |
| CEE348 | Fixed point overflow exception | SIGFPE |
| CEE349 | Fixed point divide exception | SIGFPE |
| CEE34A | Decimal overflow exception | SIGFPE |
| CEE34B | Decimal divide exception | SIGFPE |
| CEE34C | Exponent overflow exception | SIGFPE |
| CEE34D | Exponent underflow exception | SIGFPE |
| CEE34E | Significance exception | SIGFPE |
| CEE34F | Floating-point divide exception | SIGFPE |
Debug Tool interprets most input as a collection of one or more expressions. You can use expressions to alter a program variable or to extend the program by adding expressions at points that are governed by AT breakpoints.
Debug Tool evaluates C and C++ expressions following the rules presented in z/OS XL C/C++ Language Reference. The result of an expression is equal to the result that would have been produced if the same expression had been part of your compiled program.
Implicit string concatenation is supported. For example, "abc" "def" is accepted for "abcdef" and treated identically. Concatenation of wide string literals to string literals is not accepted. For example, L"abc"L"def" is valid and equivalent to L"abcdef", but "abc" L"def" is not valid.
Expressions you use during your session are evaluated with the same sensitivity to enablement as are compiled expressions. Conditions that are enabled are the same ones that exist for program statements.
During a Debug Tool session, if the current setting for WARNING is ON, the occurrence in your C or C++ program of any one of the conditions listed below causes the display of a diagnostic message.
Refer to the following topics for more information related to the material discussed in this topic.
Several considerations must be kept in mind when using the SET INTERCEPT command to intercept files while you are debugging a C application.
For CICS® only: SET INTERCEPT is not supported for CICS.
For C++, there is no specific support for intercepting IOStreams. IOStreams is implemented using C I/O which implies that:
You can use the following names with the SET INTERCEPT command during a debug session:
The behavior of I/O interception across system() call boundaries is global. This implies that the setting of INTERCEPT ON for xx in Program A is also in effect for Program B (when Program A system() calls to Program B). Correspondingly, setting INTERCEPT OFF for xx in Program B turns off interception in Program A when Program B returns to A. This is also true if a file is intercepted in Program B and returns to Program A. This model applies to disk files, memory files, and standard streams.
When a stream is intercepted, it inherits the text/binary attribute specified on the fopen statement. The output to and input from the Debug Tool log file behaves like terminal I/O, with the following considerations:
Other characteristics of intercepted files are:
Command line redirection of the standard streams is supported under Debug Tool, as shown below.
The same standard stream cannot be redirected twice on the command line. Interception is undefined if this is violated, as shown below.
Refer to the following topics for more information related to the material discussed in this topic.
An object is visible in a block or source file if its data type and declared name are known within the block or source file. The region where an object is visible is referred to as its scope. In Debug Tool, an object can be a variable or function and is also used to refer to line numbers.
In ANSI C, the four kinds of scope are:
For C++, in addition to the scopes defined for C, it also has the class scope.
An object has block scope if its declaration is located inside a block. An object with block scope is visible from the point where it is declared to the closing brace (}) that terminates the block.
An object has file scope if its definition appears outside of any block. Such an object is visible from the point where it is declared to the end of the source file. In Debug Tool, if you are qualified to the compilation unit with the file static variables, file static and global variables are always visible.
The only type of object with function scope is a label name.
An object has function prototype scope if its declaration appears within the list of parameters in a function prototype.
A class member has class scope if its declaration is located inside a class.
You cannot reference objects that are visible at function prototype scope, but you can reference ones that are visible at file or block scope if:
Debug Tool follows the same scoping rules as ANSI, except that it handles objects at file scope differently. An object at file scope can be referenced from within Debug Tool at any point in the source file, not just from the point in the source file where it is declared. Debug Tool session variables always have a higher scope than program variables, and consequently have higher precedence than a program variable with the same name. The program variable can always be accessed through qualification.
In addition, Debug Tool supports the referencing of variables in multiple load modules. Multiple load modules are managed through the C library functions dllload(), dllfree(), fetch(), and release().
Example: referencing variables and setting breakpoints in C and C++ blocks
Debug Tool supports the change and reference of all objects declared with the following storage classes:
Session variables declared during the Debug Tool session are also available for reference and change.
An object with auto storage class is available for reference or change in Debug Tool, provided the block where it is defined is active. Once a block finishes executing, the auto variables within this block are no longer available for change, but can still be examined using DESCRIBE ATTRIBUTES.
An object with register storage class might be available for reference or change in Debug Tool, provided the variable has not been optimized to a register.
An object with static storage class is always available for change or reference in Debug Tool. If it is not located in the currently qualified compile unit, you must specifically qualify it.
An object with extern storage class is always available for change or reference in Debug Tool. It might also be possible to reference such a variable in a program even if it is not defined or referenced from within this source file. This is possible provided Debug Tool can locate another compile unit (compiled with TEST(SYM)) with the appropriate definition.
It is often necessary to set breakpoints on entry into or exit from a given block or to reference variables that are not immediately visible from the current block. Debug Tool can do this, provided that all blocks are named. It uses the following naming convention:
When these block names are used in the Debug Tool commands, you might need to distinguish between nested blocks in different functions within the same source file. This can be done by naming the blocks in one of two ways:
%BLOCKzzz is contained in %BLOCKyyy, which is contained in %BLOCKxxx. The short form is always allowed; it is never necessary to specify the long form.
The currently active block name can be retrieved from the Debug Tool variable %BLOCK. You can display the names of blocks by entering:
DESCRIBE CU;
Block Identifiers tend to be longer for C++ than C because C++ functions can be overloaded. In order to distinguish one function name from the other, each block identifier is like a prototype. For example, a function named shapes(int,int) in C would have a block named shapes; however, in C++ the block would be called shapes(int,int).
You must always refer to a C++ block identifier in its entirety, even if the function is not overloaded. That is, you cannot refer to shapes(int,int) as shapes only.
Since block names can be quite long, it is not unusual to see the name truncated in the LOCATION field on the first line of the screen. If you want to find out where you are, enter:
QUERY LOCATION
and the name will be shown in its entirety (wrapped) in the session log.
Block identifiers are restricted to a length of 255 characters. Any name longer than 255 characters is truncated.
The program below is used as the basis for several examples, described after the program listing.
#pragma runopts(EXECOPS)
#include <stdlib.h>
main()
{
>>> Debug Tool is given <<<
>>> control here. <<<
init();
sort();
}
short length = 40;
static long *table;
init()
{
table = malloc(sizeof(long)*length);
·
·
·
}
sort ()
{ /* Block sort */
int i;
for (i = 0; i < length-1; i++) { /* If compiled with ISD, Block %BLOCK2; */
/* if compiled with DWARF, Block %BLOCK8 */
int j;
for (j = i+1; j < length; j++) { /* If compiled with ISD, Block %BLOCK3; */
/* if compiled with DWARF, Block %BLOCK13 */
static int temp;
temp = table[i];
table[i] = table[j];
table[j] = temp;
}
}
}
Let’s assume the program shown above is compiled with TEST(SYM). When Debug Tool gains control, the file scope variables length and table are available for change, as in:
length = 60;
The block scope variables i, j, and temp are not visible in this scope and cannot be directly referenced from within Debug Tool at this time. You can list the line numbers in the current scope by entering:
LIST LINE NUMBERS;
Now let’s assume the program is compiled with TEST(SYM, NOBLOCK). Since the program is explicitly compiled using NOBLOCK, Debug Tool will never know about the variables j and temp because they are defined in a block that is nested in another block. Debug Tool does know about the variable i since it is not in a scope that is nested.
In the program above, the function sort has the following three blocks:
| If program is compiled with the ISD compiler option | If program is compiled with the DWARF compiler option |
|---|---|
| sort | sort |
| %BLOCK2 | %BLOCK8 |
| %BLOCK3 | %BLOCK13 |
The following examples set a breakpoint on entry to the second block of sort:
The following example sets a breakpoint on exit of the first block of main and lists the entries of the sorted table.
at exit main {
for (i = 0; i < length; i++)
printf("table entry %d is %d\n", i, table[i]);
}
The following examples list the variable temp in the third block of sort. This is possible because temp has the static storage class.
You can also use the DESCRIBE command to display a list of attributes applicable to the current run-time environment. The type of information displayed varies from language to language.
Issuing DESCRIBE ENVIRONMENT displays a list of open files and conditions being monitored by the run-time environment. For example, if you enter DESCRIBE ENVIRONMENT while debugging a C or C++ program, you might get the following output:
Currently open files
stdout
sysprint
The following conditions are enabled:
SIGFPE
SIGILL
SIGSEGV
SIGTERM
SIGINT
SIGABRT
SIGUSR1
SIGUSR2
SIGABND
Qualification is a method of:
Qualification is often necessary due to name conflicts, or when a program consists of multiple load modules, compile units, and/or functions.
When program execution is suspended and Debug Tool receives control, the default, or implicit qualification is the active block at the point of program suspension. All objects visible to the C or C++ program in this block are also visible to Debug Tool. Such objects can be specified in commands without the use of qualifiers. All others must be specified using explicit qualification.
Qualifiers depend, of course, upon the naming convention of the system where you are working.
Example: using qualification in C
You can precisely specify an object, provided you know the following:
These are known as qualifiers and some, or all, might be required when referencing an object in a command. Qualifiers are separated by a combination of greater than signs (>) and colons and precede the object they qualify. For example, the following is a fully qualified object:
load_name::>cu_name:>block_name:>object
If required, load_name is the name of the load module. It is required only when the program consists of multiple load modules and when you want to change the qualification to other than the current load module. load_name is enclosed in quotation marks ("). If it is not, it must be a valid identifier in the C or C++ programming language. load_name can also be the Debug Tool variable %LOAD.
If required, CU_NAME is the name of the compilation unit or source file. The cu_name must be the fully qualified source file name or an absolute pathname. It is required only when you want to change the qualification to other than the currently qualified compilation unit. It can be the Debug Tool variable %CU. If there appears to be an ambiguity between the compilation unit name, and (for example), a block name, you must enclose the compilation unit name in quotation marks (").
If required, block_name is the name of the block. block_name can be the Debug Tool variable %BLOCK.
Example: using qualification in C
Refer to the following topics for more information related to the material discussed in this topic.
To change the point of view from the command line or a commands file, use qualifiers with the SET QUALIFY command. This can be necessary to get to data that is inaccessible from the current point of view, or can simplify debugging when a number of objects are being referenced.
It is possible to change the point of view to another load module or DLL, to another compilation unit, to a nested block, or to a block that is not nested. The SET keyword is optional.
Example: using qualification in C
The examples below use the following program.
LOAD MODULE NAME: MAINMOD
SOURCE FILE NAME: MVSID.SORTMAIN.C
short length = 40;
main ()
{
long *table;
void (*pf)();
table = malloc(sizeof(long)*length);
·
·
·
pf = fetch("SORTMOD");
(*pf)(table);
·
·
·
release(pf);
·
·
·
}
LOAD MODULE NAME: SORTMOD
SOURCE FILE NAME: MVSID.SORTSUB.C
short length = 40;
short sn = 3;
void (long table[])
{
short i;
for (i = 0; i < length-1; i++) {
short j;
for (j = i+1; j < length; j++) {
float sn = 3.0;
short temp;
temp = table[i];
·
·
·
>>> Debug Tool is given <<<
>>> control here. <<<
·
·
·
table[i] = table[j];
table[j] = temp;
}
}
}
When Debug Tool receives control, variables i, j, temp, table, and length can be specified without qualifiers in a command. If variable sn is referenced, Debug Tool uses the variable that is a float. However, the names of the blocks and compile units differ, maintaining compatibility with the operating system.
"SORTMOD"::>"MVSID.SORTSUB.C":>length = 20;
%LOAD::>"MVSID.SORTMAIN.C":>length = 20;
Because length is in the current load module and compilation unit, it can also be changed by:
length = 20;
AT CHANGE temp; AT CHANGE %BLOCK3:>temp; AT CHANGE sort:%BLOCK3:>temp; AT CHANGE %BLOCK:>temp; AT CHANGE %CU:>sort:>%BLOCK3:>temp; AT CHANGE "MVSID.SORTSUB.C":>sort:>%BLOCK3:>temp; AT CHANGE "SORTMOD"::>"MVSID.SORTSUB.C":>sort:>%BLOCK3:>temp;
The %BLOCK and %BLOCK3 variables in this example assume the program was compiled with the ISD compiler option. If the example was compiled with the DWARF compiler option, enter the DESCRIBE PROGRAM command to determine the correct %BLOCK variables.
SET QUALIFY BLOCK %BLOCK2;You can do this in a number of other ways, including:
QUALIFY BLOCK sort:>%BLOCK2;
Once the point of view changes, Debug Tool has access to objects accessible from this point of view. You can specify these objects in commands without qualifiers, as in:
j = 3; temp = 4;
QUALIFY BLOCK "MAINMOD"::>"MVSID.SORTMAIN.C":>main; LIST table[i];
You can step through methods as objects are constructed and destructed. In addition, you can step through static constructors and destructors. These are methods of objects that are executed before and after main() respectively.
If you are debugging a program that calls a function that resides in a header file, the cursor moves to the applicable header file. You can then view the function source as you step through it. Once the function returns, debugging continues at the line following the original function call.
You can step around a header file function by issuing the STEP OVER command. This is useful in stepping over Library functions (for example, string functions defined in string.h) that you cannot debug anyway.
The differences between setting breakpoints in C++ and C are described below.
AT ENTRY/EXIT sets a breakpoint in the specified block. You can set a breakpoint on methods, methods within nested classes, templates, and overloaded operators. An example is given for each below.
A block identifier can be quite long, especially with templates, nested classes, or class with many levels of inheritance. In fact, it might not even be obvious at first as to the block name for a particular function. To set a breakpoint for these nontrivial blocks can be quite cumbersome. Therefore, it is recommended that you make use of DESCRIBE CU and retrieve the block identifier from the session log.
When you do a DESCRIBE CU, the methods are always shown qualified by their class. If a method is unique, you can set a breakpoint by using just the method name. Otherwise, you must qualify the method with its class name. The following two examples are equivalent:
AT ENTRY method() AT ENTRY classname::method()
The following examples are valid:
| AT ENTRY square(int,int) | 'simple' method square |
| AT ENTRY shapes::square(int) | Method square qualified by its class shapes. |
| AT EXIT outer::inner::func() | Nested classes. Outer and inner are classes. func() is within class inner. |
| AT EXIT Stack<int,5>::Stack() | Templates. |
| AT ENTRY Plus::operator++(int) | Overloaded operator. |
| AT ENTRY ::fail() | Functions defined at file scope must be referenced by the global scope operator :: |
The following examples are invalid:
| AT ENTRY shapes | Where shapes is a class. Cannot set breakpoint on a class. (There is no block identifier for a class.) |
| AT ENTRY shapes::square | Invalid since method square must be followed by its parameter list. |
| AT ENTRY shapes:>square(int) | Invalid since shapes is a class name, not a block name. |
AT CALL gives Debug Tool control when the application code attempts to call the specified entry point. The entry name must be a fully qualified name. That is, the name shown in DESCRIBE CU must be used. Using the example
AT ENTRY shapes::square(int)
to set a breakpoint on the method square, you must enter:
AT CALL shapes::square(int)
even if square is uniquely identified.
Refer to the following topics for more information related to the material discussed in this topic.
When displaying an C++ object, only the local member variables are shown. Access types (public, private, protected) are not distinguished among the variables. The member functions are not displayed. If you want to see their attributes, you can display them individually, but not in the context of a class. When displaying a derived class, the base class within it is shown as type class and will not be expanded.
Refer to the following topics for more information related to the material discussed in this topic.
The examples below use the following definitions.
class shape { ... };
class line : public shape {
member variables of class line...
}
line edge;
To describe the attributes of the object edge, enter the following command.
DESCRIBE ATTRIBUTES edge;
The Log window displays the following output.
DESCRIBE ATTRIBUTES edge;
ATTRIBUTES for edge
Its address is yyyyyyyy and its length is xx
class line
class shape
member variables of class shape....
Note that the base class is shown as class shape _shape.
To display the attributes of class shape, enter the following command.
DESCRIBE ATTRIBUTES class shape;
The Log window displays the following output.
DESCRIBE ATTRIBUTES class shape ; ATTRIBUTES for class shape const class shape...
If a class contains static data, the static data will be shown as part of the class when displayed. For example:
class A {
int x;
static int y;
}
A obj;You can also display the static member by referencing it as A::y since each object of class A has the same value.
To avoid ambiguity, variables declared at file scope can be referenced using the global scope operator ::. For example:
int x;
class A {
int x;
·
·
·
}
}
If you are within a member function of A and want to display the value of x at file scope, enter LIST ::x. If you do not use ::, entering LIST x will display the value of x for the current object (i.e., this->x).
You might find it useful to monitor registers (general-purpose and floating-point) while stepping through your code and assembly listing by using the LIST REGISTERS command. The compiler listing displays the pseudo assembly code, including Debug Tool hooks. You can watch the hooks that you stop on and watch expected changes in register values step by step in accordance with the pseudo assembly instructions between the hooks. You can also modify the value of machine registers while stepping through your code.
You can list the contents of storage in various ways. Using the LIST REGISTERS command, you can receive a list of the contents of the General Purpose Registers or the floating-point registers.
You can also monitor the contents of storage by specifying a dump-format display of storage. To accomplish this, use the LIST STORAGE command. You can specify the address of the storage that you want to view, as well as the number of bytes.
The examples below use the following C program to demonstrate how to monitor and modify registers and storage.
int dbl(int j) /* line 1 */
{ /* line 2 */
return 2*j; /* line 3 */
} /* line 4 */
int main(void)
{
int i;
i = 10;
return dbl(i);
}
If you compile the program above using the compiler options TEST(ALL),LIST, then your pseudo assembly listing will be similar to the listing shown below.
* int dbl(int j)
ST r1,152(,r13)
* {
EX r0,HOOK..PGM-ENTRY
* return 2*j;
EX r0,HOOK..STMT
L r15,152(,r13)
L r15,0(,r15)
SLL r15,1
B @5L2
DC A@5L2-ep)
NOPR
@5L1 DS 0D
* }
@5L2 DS 0D
EX r0,HOOK..PGM-EXIT
To display a continuously updated view of the registers in the Monitor window, enter the following command:
MONITOR LIST REGISTERS
After a few steps, Debug Tool halts on line 1 (the program entry hook, shown in the listing above). Another STEP takes you to line 3, and halts on the statement hook. The next STEP takes you to line 4, and halts on the program exit hook. As indicated by the pseudo assembly listing, only register 15 has changed during this STEP, and it contains the return value of the function. In the Monitor window, register 15 now has the value 0x00000014 (decimal 20), as expected.
You can change the value from 20 to 8 just before returning from dbl() by issuing the command:
%GPR15 = 8 ;