United States |
|
|
||
Chapter 8
|
DBG> show language language: C_PLUS_PLUS DBG> |
This section describes the built-in operators that you can use in debugger commands. The operators in C++ language expressions are as follows:
Symbol | Function | Kind |
---|---|---|
* | Indirection | Prefix |
& | Address of | Prefix |
sizeof | size of | Prefix |
-- | Unary minus (negation) | Prefix |
+ | Addition | Infix |
-- | Subtraction | Infix |
* | Multiplication | Infix |
/ | Division | Infix |
% | Remainder | Infix |
<< | Left shift | Infix |
>> | Right shift | Infix |
== | Equal to | Infix |
!= | Not equal to | Infix |
> | Greater than | Infix |
>= | Greater than or equal to | Infix |
< | Less than | Infix |
<= | Less than or equal to | Infix |
~ (tilde) | Bit-wise NOT | Prefix |
& | Bit-wise AND | Infix |
| | Bit-wise OR | Infix |
^ | Bit-wise exclusive OR | Infix |
! | Logical NOT | Prefix |
&& | Logical AND | Infix |
|| | Logical OR | Infix |
Because the exclamation point (!) is an operator, it cannot be used in C++ programs as a comment delimiter. However, to permit debugger log files to be used as debugger input, the debugger still recognizes the exclamation point as a comment delimiter if it is the first nonspace character on a line. In C++ language mode, the debugger accepts a forward slash immediately followed by an asterisk (/*) as the comment delimiter. The comment continues to the end of the current line. A matching asterisk immediately followed by a slash (*/) is neither needed nor recognized.
The debugger accepts the asterisk (*) prefix as an indirection operator in both C++ language expressions and debugger address expressions. In address expressions, the asterisk prefix is synonymous to the period (.) prefix or the at sign (@) prefix when the language is set to C++.
To prevent unintended modifications to the program being debugged, the debugger does not support any of the assignment operators in C++ (or any other language). Thus, such operators as =, +=, --=, ++, and -- are not recognized. To alter the contents of a memory location, you must do so with an explicit deposit command.
The supported constructs in language and address expressions for C++ are as follows:
Symbol | Construct |
---|---|
[ ] | Subscripting |
. (period) | Structure component selection |
-> | Pointer dereferencing |
Predefined data types supported in the debugger are as follows:
C++ Data Type | OpenVMS Data Type Name |
---|---|
int | Longword Integer (L) |
unsigned int | Longword Unsigned (LU) |
short int | Word Integer (W) |
unsigned short int | Word Unsigned (WU) |
char | Byte Integer (B) |
unsigned char | Byte Unsigned (BU) |
float | F_Floating (F) |
double | D_Floating (D) |
enum | None |
struct | None |
union | None |
class | None |
Pointer type | None |
Array type | None |
Uppercase letters in parentheses represent standard data type mnemonics in the OpenVMS common language environment. For more information, see OpenVMS Programming Interfaces: Calling a System Routine.
Supported data types specific to OpenVMS Alpha systems are as follows:
C++ Data Type | OpenVMS Alpha Data Type Name |
---|---|
__int16 | Word Integer (W) |
unsigned __int16 | Word Unsigned (WU) |
__int32 | Longword Integer (L) |
unsigned __int32 | Longword Unsigned (LU) |
__int64 | Quadword Integer (Q) |
unsigned __int64 | Quadword Unsigned (QU) |
__g_float | G_Floating (G) |
__f_float | F_Floating (F) |
__s_float | IEEE S_Floating (FS) |
__t_float | IEEE T_Floating (FT) |
Discussions in Section 8.2 use the term qualified class names to describe how to compose the names of class members when using the debugger. If a class is not defined within another class, the qualified class name is merely the name of the class itself. However, if a class is nested within another class, the name of the immediately containing class must precede it separated with a pair of colons (::). If the containing class is itself nested, its name must be prefixed, and so on.
The following are examples of properly qualified class names:
DBG> set break C::f ! f is a member of class C DBG> set break FOO::BAR::BAZ::g ! g is a member of BAZ, ! which is nested in BAR, ! which is nested in FOO |
This section describes how to use the OpenVMS Debugger with C++ data.
This section describes how to refer to data members that are not declared static.
To refer to a nonstatic data member that is defined directly in a C++ class (or a struct or union ), use its name just as with a C language struct or union member. The following example shows the correct use of a nonstatic data member reference:
DBG> examine x.m, p->m |
Currently, debugger support distinguishes nonstatic data members inherited from various base classes by prefixing their names with a sequence of significant base class names on the inheritance path to the member, and then the class that the member is declared in. A base class on a path from an object to a member is significant if the base class in question is derived from using multiple inheritance. Thus, a base class is significant if it is mentioned in a base list containing more than one base specifier.
This notation generates the minimum number of base class prefixes necessary to describe the inheritance path to a base class, because it involves naming only those base classes where one must choose where to proceed next when traversing the path. When no multiple inheritance is involved, the reference has the following syntax:
CLASS::member |
Specify the sequence of significant base classes in the order from the object's most derived significant class, to the significant base class closest to the object.
For example, consider the inheritance graph for the following declarations:
struct A { int a_member; }; struct B : A { int b_member; }; struct C { int c_member; }; struct D : B, C { int d_member; }; struct E : D { int e_member; }; struct F { int f_member; }; struct G : F { int g_member; }; struct H : E, G { int h_member; }; struct I : H { int i_member; }; struct J : I { int j_member; }; static J j_object; |
Because classes B, C, E, and G are mentioned in base lists, which involve multiple inheritance, they are the significant classes that appear as prefixes. The following examples are references to all the members through debugger deposit commands. Note that the class of the inherited member itself appears before the member name, regardless of whether or not the member belongs to a significant class.
DBG> deposit j_object.E::B::A::a_member = 1 DBG> deposit j_object.E::B::b_member = 2 DBG> deposit j_object.E::C::c_member = 3 DBG> deposit j_object.E::D::d_member = 4 DBG> deposit j_object.E::e_member = 5 DBG> deposit j_object.G::F::f_member = 6 DBG> deposit j_object.G::g_member = 7 DBG> deposit j_object.H::h_member = 8 DBG> deposit j_object.I::i_member = 9 DBG> deposit j_object.j_member = 10 DBG> examine j_object 6212\j_object E::B::A::a_member: 1 E::B::b_member: 2 E::C::c_member: 3 E::D::d_member: 4 E::e_member: 5 G::F::f_member: 6 G::g_member: 7 H::h_member: 8 I::i_member: 9 j_member: 10 DBG> |
In the OpenVMS Debugger, symbolic access to data members of virtual base classes is currently not supported. Objects of classes with virtual base classes have a pointer member named __bptr .
The following examples show the correct use of static data member references:
DBG> examine C::s DBG> examine FOO::BAR::BAZ::sdm |
To access the values of objects declared with a reference, use the name of the object.
The OpenVMS Debugger treats data members declared with a reference type as though they were pointer variables; thus, you must use the * or -> dereference operators on their names.
For example, consider the following code:
class C { public: int &ref_mem; C(int &arg) : ref_mem(arg) {} }; main() { auto int obj = 5; auto int &ref_obj = obj; auto C c(obj); obj = 23; } ... |
The following sequence shows the correct way to use the debugger to examine the members:
stepped on return from routine REF\main to REF\main\%LINE 13+16 13: } DBG> examine obj, ref_obj REF\main\obj: 23 REF\main\ref_obj: 23 DBG> examine c REF\main\c ref_mem: 2144211292 DBG> symbolize c.ref_mem address 7FCE1154: REF\main\c DBG> examine *c.ref_mem *REF\main\c.ref_mem: 23 |
Values that are pointers to members are represented as a struct with the members __thunk and __offset . The __thunk member contains the address of the member pointed to. The __offset member contains an offset adjustment when the pointer to member refers to a multiply inherited base class. For example:
struct A { int mem0; }; struct B { int mem1; int mem2; }; struct C : public A, public B { int mem3; int mem4; }; /* pointer to member initalized with pointer to member * address of the same class. */ int C::*pmc = &C::mem2; /* pointer to member initialized with pointer to member * address of one of the * base classses. An implicit * conversion occurs. */ int C::*pmbc = &B::mem2; extern "C" printf (const char *,...); main() { C *cinst = new C; cinst->*pmc = 7; printf("cinst pointer to member value is %d\n",cinst->mem2); } |
If you compile this program with the /nooptimize/debug qualifiers, from the last line in the program, you can use the pointer to member to display the following information:
DBG>set break %line 31 DBG>go DBG>go cinst pointer to member value is 7 DBG> Set Mode Noscreen; Set Step Source DBG> ex cinst PTRMEMBER\main\cinst: 004136F8 DBG> ex *cinst *PTRMEMBER\main\cinst A::mem0: 00000000 B::mem1: 00000000 B::mem2: 00000007 mem3: 00000000 mem4: 00000000 DBG> ex pmc PTRMEMBER\pmc __thunk: 00010060 __offset: 00000000 DBG> call 00010060(004136F8) value returned is 00413700 DBG> ex 00413700 00413700: 00000007 DBG> ex pmbc PTRMEMBER\pmbc __thunk: 00010098 __offset: 00000004 DBG> call 00010098(004136F8+4) value returned is 00413700 DBG> ex 00413700 00413700: 00000007 DBG> exit |
To examine and display the value of an object or member by type, use the command examine/type . Similarly, you can modify the value of an expression to be deposited to a type you specify by using the command deposit/type . With the /type qualifier, the syntax for these commands is as follows:
deposit/type=(name) examine/type=(name) |
The type denoted by name must be the name of a variable or data type declared in the program. The /type qualifier is particularly useful for referencing C++ objects that have been declared with more than one type.
This section describes how to reference the various kinds of functions and function arguments.
To find the symbolic names of functions in your code, use the show symbol command. If the function is overloaded, use the wildcard character (*) in the name specification to display the overloaded symbol names.
For example, consider the following code:
class base { public: base(); base( int ); ~base(); int base_f1(); void base_f2(); void base_f2( int ); void base_f2( char ); }; |
The following sequence shows how to display overloaded symbols and determine the appropriate function reference:
DBG> set break base::base_f2 %DEBUG-E-NOTUNQOVR, symbol 'base::base_f2' is overloaded use SHOW SYMBOL to find the unique symbol names DBG> show symbol *base_f2 overloaded symbol CXX_T10_179\base::base_f2 overloaded instance CXX_T10_179\base::base_f2__1 overloaded instance CXX_T10_179\base::base_f2__2 overloaded instance CXX_T10_179\base::base_f2__3 DBG> set break base::base_f2__2 DBG> step stepped to CXX_T10_179\main\%LINE 20 20: x.base_f2(); DBG> step stepped to CXX_T10_179\main\%LINE 21 21: x.base_f2(5); DBG> step break at routine CXX_T10_179\base::base_f2__2 12: void base_f2( int ) {} DBG> step stepped to CXX_T10_179\main\%LINE 22 22: x.base_f2('W'); stepped to CXX_T10_179\main\%LINE 22 DBG> go %DEBUG-I-EXITSTATUS, is '%SYSTEM-S-NORMAL, normal successful completion' DBG> ^Z |
If the member function is overloaded, append the suffix __ integer-number. The following examples show the correct use of member function references:
DBG> set break MYSTRING::length DBG> set break MYCOMPLEX::format__1, MYCOMPLEX::format__2 |
To refer to a constructor, state the name. If a constructor is overloaded, append the suffix __ integer-number. The following examples show the correct use of constructor references:
DBG> set break FOO DBG> set break MYSTRING__1 |
The following example shows the correct use of a destructor reference:
DBG> set break ~FOO |
The set of atomic types are drawn from the following set of names:
void char signed_char unsigned_char signed_short unsigned_short int signed_int unsigned_int signed_long unsigned_long float double long_double |
Pointer types are named (type)* . Reference types are named (type)& . The types struct , union , class , and enum are named by their tags, and the qualifiers const and volatile precede their types with a space in between. For example:
DBG> set break C::int, C::(const S)& |
The following operators may be overloaded by user-defined functions:
+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && | ++ -- ->* , -> [] () delete new |
If the function is overloaded, append the suffix __ integer_number to the operator characters. In particular, this suffix is necessary if both unary and binary instances of an operator such as + are defined, or if prefix instances of ++ or -- are defined.
The following examples show the correct use of user-defined function references:
DBG> set break MYSTRING::+ DBG> set break COUNTER::++__1, COUNTER::++__2 |
See §7.2 of The C++ Programming Language, 3nd Edition for details.
In OpenVMS Debugger referencing, you use this , *this , and this->m as follows:
DBG> examine this |
DBG> examine *this |
DBG> examine this->m |
When calling C++ member functions from the debugger, you cannot make the call using the same syntax that you would use in a C++ source file. You must call the class qualified member function name with the object as the first argument. For example:
extern "C" void printf(const char *,...); class C12 { int i; int j; public: C12() : i(1), j(2) {} method(); }; C12::method() { i = i + j; printf("C12::method called: i=%d, j=%d\n",i,j); } main() { C12 cinst; cinst.method(); printf("End of example.\n"); } |
When you compile this example with /debug/noopt , you can call the member function with the following command:
DBG> call C12::method(cinst) |
Previous | Next | Contents | Index |
privacy statement and legal notices |