Document revision date: 30 March 2001

## OpenVMS Debugger Manual

Previous | Contents | Index

### C.6.9 Limitations on Debugger Support for C++

The following limitations apply when you debug a C++ program:

- You cannot specify a template by name in a debugger command. You must use the name of the instantiation of the template.
- In C++, expressions in the instantiated template name can be full constant expressions, such as stack<double,f*10>. This form is not yet supported in the debugger; you must enter the value of the expression (for example, if f is 10 in the stack example, you must enter 100).

Example C-1 contains CXXDOCEXAMPLE.C, a C++ example program.

Example C-1 C++ Example Program CXXDOCEXAMPLE.C

    int x = 0;

    struct A
        {
        int i,j;
        void f() {}
        virtual void h() {};
        A() { i=x++; j=x++; }
        };

    struct B1 : virtual A
        {
        int i;
        void f() {}
        virtual void h() {}
        B1() { i=x++; }
        };

    struct B2 : virtual A
        {
        int i;
        void f() {}
        virtual void h() {}
        B2() { i=x++; }
        };

    struct C : B1, B2
        {
        int j;
        static int s;
        void g( int ) {}
        void g( long ) {}
        void g( char ) {}
        void h() {}
        operator ==( C& ) { return 0; }
        C() { j=x++; }
        ~C() {}
        };

    int C::s = 42;

    main()
        {
        A a; B1 b1; B2 b2; C c;
        A *ptr = &a;
        int x = 101;
        x++;

        c.s++;
        c.B2::i++;
        c.s++;

        b1.f();
        c.B1::f();
        c.g(1);
        c.g( (long) 1 );
        c.g( 'a' );
        }

Example C-2 contains a sample debugging session of the program contained in Example C-1.

Example C-2 C++ Debugging Example

    DBG> GO
    break at routine CXXDOCEXAMPLE\main
        44:     A a; B1 b1; B2 b2; C c;
    DBG> STEP
    stepped to CXXDOCEXAMPLE\main\%LINE 45
        45:     A *ptr = &a;
    DBG> STEP
    stepped to CXXDOCEXAMPLE\main\%LINE 46
        46:     int x = 101;
    DBG> STEP
    stepped to CXXDOCEXAMPLE\main\%LINE 47
        47:     x++;
    !!
    !! Displaying class information
    !!
    DBG> SHOW SYMBOL /TYPE C
    type C
        struct (C, 13 components), size: 40 bytes
    overloaded name C
           instance C::C(void)
           instance C::C(const C &)
    DBG> SHOW SYMBOL /FULL C
    type C
        struct (C, 13 components), size: 40 bytes
          inherits: B1, size: 24 bytes, offset: 0 bytes
                    B2, size: 24 bytes, offset: 12 bytes
          contains the following members:
            overloaded name C::g
                   instance C::g(int)
                   instance C::g(long)
                   instance C::g(char)
            j : longword integer, size: 4 bytes, offset: 24 bytes
            s : longword integer, size: 4 bytes, address: #  [static]
            overloaded name C
            int ==(C &)
            C & =(const C &)
            void h(void)   [virtual]
            ~C(void)
            __vptr : typed pointer type, size: 4 bytes, offset: 4 bytes
            __bptr : typed pointer type, size: 4 bytes, offset: 8 bytes
            structure has been padded, size: 4 bytes, offset: 36 bytes
    overloaded name C
           instance C::C(void)
           instance C::C(const C &)
    !!
    !! Displaying information about base classes
    !!
    DBG> SHOW SYMBOL /FULL B1
    type B1
        struct (B1, 8 components), size: 24 bytes
          inherits: virtual A
          is inherited by: C
          contains the following members:
            i : longword integer, size: 4 bytes, offset: 0 bytes
            overloaded name B1
            void f(void)
            B1 & =(const B1 &)
            void h(void)   [virtual]
            __vptr : typed pointer type, size: 4 bytes, offset: 4 bytes
            __bptr : typed pointer type, size: 4 bytes, offset: 8 bytes
            structure has been padded, size: 12 bytes, offset: 12 bytes
    overloaded name B1
           instance B1::B1(void)
           instance B1::B1(const B1 &)
    !!
    !! Displaying class member information
    !!
    DBG> SHOW SYMBOL /FULL j
    record component C::j
        address: offset 24 bytes from beginning of record
        atomic type, longword integer, size: 4 bytes
    record component A::j
        address: offset 4 bytes from beginning of record
        atomic type, longword integer, size: 4 bytes
    !!
    !! Simple object display
    !!
    DBG> EXAMINE a
    CXXDOCEXAMPLE\main\a: struct A
        i:  0
        j:  1
        __vptr:     131168
    !!
    !! Using *, -> and . to access objects and members
    !!
    DBG> EXAMINE ptr
    CXXDOCEXAMPLE\main\ptr:         40
    DBG> EXAMINE *ptr
    *CXXDOCEXAMPLE\main\ptr: struct A
        i:  0
        j:  1
        __vptr:     131168
    DBG> EXAMINE a.i
    CXXDOCEXAMPLE\main\a.i: 0
    DBG> EXAMINE ptr->i
    CXXDOCEXAMPLE\main\ptr->i:      0
    !!
    !! Complicated object example
    !!
    DBG> EXAMINE c
    CXXDOCEXAMPLE\main\c: struct C
        inherit B1
            inherit virtual A
                i:  8
                j:  9
                __vptr:     131200
            i:      10
            __vptr: 131232
            __bptr: 131104
        inherit B2
            inherit virtual A  (already printed, see above)
            i:      11
            __vptr: 131280
            __bptr: 131152
        j:  12
        __vptr:     131232
        __bptr:     131104
    !!
    !! The debugger using C++ symbol lookup rules (to match c.j)
    !! and then the use of :: to specify a particular member named j.
    !!
    DBG> EXAMINE c.j
    CXXDOCEXAMPLE\main\c.j: 12
    DBG> EXAMINE c.A::j
    CXXDOCEXAMPLE\main\c.A::j:      9
    !!
    !! Using the global scope resolution operator.
    !!
    DBG> EXAMINE x
    CXXDOCEXAMPLE\main\x:   101
    DBG> EXAMINE ::x
    CXXDOCEXAMPLE\x:        13
    !!
    !! Handling ambiguous member references.
    !!
    DBG> EXAMINE c.i
    %DEBUG-I-AMBIGUOUS, 'i' is ambiguous, matching the following
        CXXDOCEXAMPLE\main\c.B1::i
        CXXDOCEXAMPLE\main\c.B2::i
    %DEBUG-E-REENTER, reenter the command using a more precise pathname
    DBG> EXAMINE c.B1::i
    CXXDOCEXAMPLE\main\c.B1::i:     10
    !!
    !! Refering to static data members: with . and with ::
    !!
    DBG> EXAMINE c.s
    CXXDOCEXAMPLE\main\c.s: 42
    DBG> EXAMINE C::s
    C::s:   42
    !!
    !! Setting watchpoints on objects.  All non-static data members
    !! are watched (including those in base classes).  Static data
    !! members are not watched.  Of course watchpoints on static data
    !! members can be set explicitly.
    !!
    DBG> SET WATCH c
    %DEBUG-I-WPTTRACE, non-static watchpoint, tracing every instruction
    DBG> GO
    watch of CXXDOCEXAMPLE\main\c.i at CXXDOCEXAMPLE\main\%LINE 50+8
        50:     c.B2::i++;
       old value: 11
       new value: 12
    break at CXXDOCEXAMPLE\main\%LINE 51
        51:     c.s++;
    DBG> SET WATCH c.s
    DBG> GO
    watch of CXXDOCEXAMPLE\main\c.s at CXXDOCEXAMPLE\main\%LINE 51+16
        51:     c.s++;
       old value: 43
       new value: 44
    break at CXXDOCEXAMPLE\main\%LINE 53
        53:     b1.f();
    !!
    !! Basic member lookup applies to functions.
    !!
    DBG> EXAMINE /SOURCE b1.f
    module CXXDOCEXAMPLE
        14:     void f() {}
    DBG> SET BREAK B1::f
    DBG> GO
    break at routine B1::f
        14:     void f() {}
    !!
    !! Support for 'this'.
    !!
    DBG> EXAMINE this
    B1::f::this:            16
    DBG> EXAMINE *this
    *B1::f::this: struct B1
        inherit virtual A
            i:      2
            j:      3
            __vptr: 131184
        i:  4
        __vptr:     131248
        __bptr:     131120
    DBG> EXAMINE this->i
    B1::f::this->i: 4
    DBG> EXAMINE this->j
    B1::f::this->A::j:      3
    DBG>EXAMINE i
    B1::f::this->i: 4
    DBG> EXAMINE j
    B1::f::this->A::j:      3
    !!
    !! Support for virtual functions.
    !!
    !! We are at the call to B1::f made at 'b1.f()'.
    !! Here this->h matches B1::h.
    !!
    DBG> EXAMINE /SOURCE %LINE 53
    module CXXDOCEXAMPLE
        53:     b1.f();
    DBG> SET BREAK this->h
    DBG> SHOW BREAK
    breakpoint at routine B1::f
    breakpoint at routine B1::h
    !!
    !! We are at the call to B1::f made at 'c.B1::f()'.
    !! Here this->h matches C::h.
    !!
    DBG> GO
    break at routine B1::f
        14:     void f() {}
    DBG> EXAMINE /SOURCE %LINE 54
    module CXXDOCEXAMPLE
        54:     c.B1::f();
    DBG> SET BREAK this->h
    DBG> SHOW BREAK
    breakpoint at routine B1::f
    breakpoint at routine B1::h
    breakpoint at routine C::h
    !!
    !! Handling overloaded functions
    !!
    DBG> SET BREAK g
    %DEBUG-I-NOTUNQOVR, symbol 'g' is overloaded
    overloaded name C::g
           instance C::g(int)
           instance C::g(long)
           instance C::g(char)
    %DEBUG-E-REENTER, reenter the command using a more precise pathname
    DBG> SET BREAK g(int)

    DBG> CANCEL BREAK/ALL
    !!
    !! Working with constructors, destructors, and operators.
    !!
    DBG> SET BREAK C
    %DEBUG-I-NOTUNQOVR, symbol 'C' is overloaded
    overloaded name C
           instance C::C(void)
           instance C::C(const C &)
    %DEBUG-E-REENTER, reenter the command using a more precise pathname
    DBG> SHOW SYMBOL /FULL ~C
    routine C::~C
       type signature: ~C(void)
        code address: #, size: 152 bytes
        procedure descriptor address: #
    DBG> SET BREAK %NAME'~C'
    DBG> SET BREAK %NAME'=='
    %DEBUG-W-UNALLOCATED, '==' is not allocated in memory (optimized away)
    %DEBUG-E-CMDFAILED, the SET BREAK command has failed
    DBG> SHOW SYMBOL /FULL ==
    routine C::==
        type signature: int ==(C &)
        address: unallocated
    DBG> SHOW BREAK
    breakpoint at routine C::~C
    DBG> EXIT

## C.7 C++

The following sections describe debugger support for C++ programs compiled with C++ compiler versions prior to Version 5.5.

See Section C.6 for a description of debugger support for C++ programs compiled with Version 5.5 or later (Alpha only).

### C.7.1 The %name Lexical Function

Use of the %name lexical function is required with debugger commands to reference certain entities in Compaq C++, such as functions and data members. When used, this function is always placed between the command and the reference. Examples of correct usage are shown in the following sections for cases where its use is required.

### C.7.2 Operators in Language Expressions

Supported C++ operators in language expressions include:

Kind | Symbol | Function
--- | --- | ---
Prefix | * | Indirection
Prefix | & | Address of
Prefix | sizeof | size of
Prefix | - | Unary minus (negation)
Infix | + | 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
Prefix | ~ (tilde) | Bit-wise NOT
Infix | & | Bit-wise AND
Infix | | | Bit-wise OR
Infix | ^ | Bit-wise exclusive OR
Prefix | ! | Logical NOT
Infix | && | Logical AND
Infix | || | Logical OR

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 an exclamation point as a comment delimiter if it is the first nonspace character on a line. In C++ language mode, the debugger accepts /* as the comment delimiter. The comment continues to the end of the current line. (A matching */ 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 `*` prefix is synonymous to the period (.) prefix or 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.

### C.7.3 Constructs in Language and Address Expressions

Supported constructs in language and address expressions for C++ follow:

Symbol | Construct
--- | ---
[ ] | Subscripting
. (period) | Structure component selection
-> | Pointer dereferencing

### C.7.4 Data Types

Supported C++ data types follow:

C++ Data Type | Operating System Data Type Name
--- | ---
__int64 (Alpha specific) | Quadword Integer (Q)
unsigned __int64 (Alpha specific) | Quadword Unsigned (QU)
__int32 (Alpha specific) | Longword Integer (L)
unsigned __int32 (Alpha specific) | Longword Unsigned (LU)
int | Longword Integer (L)
unsigned int | Longword Unsigned (LU)
__int16 (Alpha specific) | Word Integer (W)
unsigned __int16 (Alpha specific) | Word Unsigned (WU)
short int | Word Integer (W)
unsigned short int | Word Unsigned (WU)
char | Byte Integer (B)
unsigned char | Byte Unsigned (BU)
float | F_Floating (F)
__f_float (Alpha specific) | F_Floating (F)
double | D_Floating (D)
double | G_Floating (G)
__g_float (Alpha specific) | G_Floating (G)
float (Alpha specific) | IEEE S_Floating (FS)
__s_float (Alpha specific) | IEEE S_Floating (FS)
double (Alpha specific) | IEEE T_Floating (FT)
__t_float (Alpha specific) | IEEE T_Floating (FT)
enum | (None)
struct | (None)
union | (None)
Pointer Type | (None)
Array Type | (None)

Floating-point numbers of type float may be represented by F_Floating or IEEE S_Floating, depending on compiler switches.

Floating-point numbers of type double may be represented by IEEE T_Floating, D_Floating, or G_Floating, depending on compiler switches.

### C.7.5 Case Sensitivity

Symbol names are case sensitive for C++, meaning that uppercase and lowercase letters are treated as different characters.

### C.7.6 Qualified Class Names

Discussions in some of the following sections 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 %name 'C::f'             ! f is a member of class C
    DBG> set break %name 'FOO::BAR::BAZ::g' ! g is a member of BAZ,
                                            ! which is nested in BAR,
                                            ! which is nested in FOO

### C.7.7 Using the Debugger with C++ Data

This section describes how to use the debugger with C++ data.

#### C.7.7.1 Nonstatic Data Members

This section describes how to refer to data members that are not declared static.

##### C.7.7.1.1 Noninherited Data Members

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

##### C.7.7.1.2 Inherited Data Members

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 inheritances. 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 is of the following form:

    %name'CLASS::member'

To refer to nonstatic data members inherited from base classes of an object, quote the sequence of significant qualified base class names and the member name (separated by double colons) with %name. 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.

##### C.7.7.1.3 Inherited Virtual Data Members

In the debugger, symbolic access to data members of virtual base classes is currently not supported. The one exception to this is that the pointer member named __bptr is present in such objects.

#### C.7.7.2 Static Data Members

To refer to a static data member, quote its qualified class name, two colons (::), and then the member name, with %name.

The following examples show the correct use of static data member references:

    DBG> examine %name 'C::s'
    DBG> examine %name 'FOO::BAR::BAZ::sdm'

#### C.7.7.3 Reference Objects and Reference Members

To access the values of objects declared with a reference, use the name of the object.

The 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

Previous | Next | Contents | Index

| privacy and legal statement |
4538PRO_069.HTML