DEC C++
Using DEC C++ for DIGITAL UNIX Systems


Previous Contents Index

8.10 Setting Breakpoints in Member Functions

When you set a breakpoint in a C function, the debugger confirms the breakpoint by echoing the breakpoint command along with the status number for the breakpoint. When you set a breakpoint in a C++ function, the debugger also prints the type signature of the function in which the breakpoint was set.

To set a breakpoint that stops in a member function, use one of the following syntax lines:
stop in function
stop in class_name::function

This form of specifying a breakpoint in a function uses the static class type information to determine the address of the function at which to set the breakpoint, and presumes that no run-time information from an object is needed.

In Example 8-9 a breakpoint is set for member function bar of class S.

Example 8-9 Setting Breakpoints in Member Functions

(Ladebug) stop in S :: bar
[#1: stop in S::bar(void) ] 
(Ladebug) status
#1 PC==0x120000658 in S::bar(void) "c++ex.C":18 { break } 
(Ladebug) run
[1] stopped at [S::bar(void):18 0x120000658]       
     18      return j; 
(Ladebug) where
>0  0x120000658 in ((S*)0x120000658)->bar() c++ex.C:18 
#1  0x120000750 in main() c++ex.C:26 
(Ladebug) 

If you need run-time information from the object to determine the correct virtual function at which to set a breakpoint, qualify the function name with the object using one of the following syntax lines:
stop in object.function
stop in objectpointer->function

Setting the breakpoint in this way causes the debugger to stop at the member function in all objects declared with the same class type as the specified object. In Example 8-10, objects s and t are both declared to be of class type S. A breakpoint is set for member function bar. The first time the debugger stops at bar() is for object s. The second time the debugger stops in bar() for object t.

Example 8-10 Setting Breakpoints in Virtual Member Functions

(Ladebug) stop in main
[#1: stop in main(void) ] 
(Ladebug) run
[1] stopped at [main(void):26 0x120000744] 
     26      int result = s.bar(); 
(Ladebug) stop in s.bar
[#2: stop in S::bar(void) ] 
(Ladebug) status
#1 PC==0x120000744 in main(void) "c++ex.C":26 { break } 
#2 PC==0x120000658 in S::bar(void) "c++ex.C":18 { break } 
(Ladebug) print &s
0x140000000 
(Ladebug) print &t
0x140000008 
(Ladebug) cont
[2] stopped at [S::bar(void):18 0x120000658]       
     18      return j; 
(Ladebug) where
>0  0x120000658 in ((S*)0x140000000)->bar() c++ex.C:18 
#1  0x120000750 in main() c++ex.C:26 
(Ladebug) cont
[2] stopped at [S::bar(void):18 0x120000658]       
     18      return j; 
(Ladebug) where
>0  0x120000658 in ((S*)0x140000008)->bar() c++ex.C:18 
#1  0x12000076c in main() c++ex.C:27 
(Ladebug) 

To set a breakpoint that stops only in the member function for this specific object and not all instances of the same class type, you must specify this as an additional conditional clause to the stop command. Use one of the following syntax lines:
stop in object.function if & object :=,= this
stop in objectpointer->function if & objectpointer :=,= this

This form of the breakpoint command instructs the debugger to stop in the function only for the object specified by the this pointer. In Example 8-11, which is running the same program as Example 8-10, the breakpoint is set for the member function for object s only. After stopping in bar() for object s, further execution of the program results in the program running to completion.

Example 8-11 Setting Breakpoints in Member Functions for a Specific Object

(Ladebug) stop in s.bar if &s==this
[#2: stop in s.bar if &s==this ] 
(Ladebug) status
#1 PC==0x120000744 in main(void) "c++ex.C":26 { break } 
#2 (PC==0x120000658 in S::bar(void) "c++ex.C":18 and if &s==this) {break} 
(Ladebug) print &s
0x140000000 
(Ladebug) cont
[2] stopped at [S::bar(void):18 0x120000658]       
     18      return j; 
(Ladebug) where
>0  0x120000658 in ((S*)0x10000010)->bar() c++ex.C:18 
#1  0x120000750 in main() c++ex.C:26 
(Ladebug) cont
Thread has finished executing 
(Ladebug) 

8.10.1 Setting Breakpoints in Overloaded Functions

To set a breakpoint in an overloaded function, you must provide the full type signature of the function. Use one of the following command syntax lines:
stop in function (type_signature)
stop in class_name::function (type_signature)

If the desired version of the function has no parameters, you must enter void for the type signature. In Example 8-12 the breakpoint is set for specific versions of the overloaded function foo.

Example 8-12 Setting Breakpoints in Specific Overloaded Functions

(Ladebug) class S
class S  { 
  int i; 
  float f; 
  double d; 
  char c; 
  S (void); 
  ~S (void); 
  int foo (void); 
  int foo ( S); 
  int foo ( S *); 
  int foo (int&); 
  int foo (const int&); 
  int foo (float*&); 
  int foo (int, float, char *, unsigned short, long&, const char*&); 
  int foo (const double *); 
  int foo (char); 
  void foo (short); 
  void foo (unsigned); 
  void foo (long); 
  void foo (int, float, char *, unsigned short, long&, char*&); 
  void foo (double); 
  void foo (char *); 
  void foo (const char *); 
} 
(Ladebug) whatis foo
Overloaded Function. Functions are: 
int S::foo(void) 
int S::foo(S) 
int S::foo(S*) 
int S::foo(int&) 
int S::foo(const int&) 
int S::foo(float*&) 
int S::foo(int, float, char*, unsigned short, long&, const char*&) 
int S::foo(const double*) 
int S::foo(char) 
void S::foo(short) 
void S::foo(unsigned) 
void S::foo(long) 
void S::foo(int, float, char*, unsigned short, long&, char*&) 
void S::foo(double) 
void S::foo(char*) 
void S::foo(const char*) 
(Ladebug) stop in foo(double)
[#1: stop in void S::foo(double) ] 
(Ladebug) stop in foo(void)
[#2: stop in int S::foo(void) ] 
(Ladebug) status
#1 PC==0x120001508 in void S::foo(double) "c++over.C":156 { break } 
#2 PC==0x120000ef4 in int S::foo(void) "c++over.C":59 { break } 
(Ladebug) 

To set a breakpoint that stops in all versions of an overloaded function, use one of the following syntax lines:
stop in all function
stop in all class_name::function

In Example 8-13 the breakpoint is set for all versions of the overloaded function foo.

Example 8-13 Setting Breakpoints in All Versions of an Overloaded Function

(Ladebug) class S
class S  { 
  int i; 
  float f; 
  double d; 
  char c; 
  S (void); 
  ~S (void); 
  int foo (void); 
  int foo ( S); 
  int foo ( S *); 
  int foo (int&); 
  int foo (const int&); 
  int foo (float*&); 
  int foo (int, float, char *, unsigned short, long&, const char*&); 
  int foo (const double *); 
  int foo (char); 
  void foo (short); 
  void foo (unsigned); 
  void foo (long); 
  void foo (int, float, char *, unsigned short, long&, char*&); 
  void foo (double); 
  void foo (char *); 
  void foo (const char *); 
} 
(Ladebug) stop in all foo
[#1: stop in all foo ] 
(Ladebug) 

You can also set a breakpoint in an overloaded function by setting a breakpoint at the line number where the function begins. Be sure the current file context points to the file containing the function's source code before setting the breakpoint. In Example 8-14 the breakpoint is set for the overloaded functions by line number.

Example 8-14 Setting Breakpoints in Overloaded Functions by Line Number

(Ladebug) stop at 59
[#1: stop at "c++over.C":59 ] 
(Ladebug) stop at 156
[#2: stop at "c++over.C":156 ] 
(Ladebug) status
#1 PC==0x120000ef4 in S::foo(void) "c++over.C":59 { break } 
#2 PC==0x120001508 in S::foo(double) "c++over.C":156 { break } 
(Ladebug) 

8.10.2 Setting Breakpoints in Constructors and Destructors

To set a breakpoint in a constructor, use one of the following syntax lines:
stop in class_name::class_name [(type_signature)]
stop in class_name [(type_signature)]

The type signature is necessary only to resolve the ambiguity for a constructor that is overloaded. In Example 8-15, a breakpoint is set in a constructor.

Example 8-15 Setting Breakpoints in Constructors

(Ladebug) class S
class S  { 
  int i; 
  int j; 
  S (void); 
  ~S (void); 
  int foo (void); 
  virtual int bar (void); 
} 
(Ladebug) stop in S
[#1: stop in S::S(void) ] 
(Ladebug) status
#1 PC==0x1200005b8 in S::S(void) "c++ex.C":5 { break } 
(Ladebug) 

You can similarly set a breakpoint in a destructor using the following syntax:
stop in ~class_name

In Example 8-16, the breakpoint is set for the destructor.

Example 8-16 Setting Breakpoints in Destructors

(Ladebug) stop in  S
[#1: stop in ~S::S(void) ] 
(Ladebug) status
#1 PC==0x1200005f8 in S::~S(void) "c++ex.C":6 { break } 
(Ladebug) 

As with any function's type signature specification, constructors and destructors that have no parameters must be referenced with a type signature of void.

8.11 Calling Overloaded Functions

To call overloaded functions from the debugger, you must set $overloadmenu to 1. Then, use the following call command syntax:
call function ([parameter[,...]])

The debugger will call the function that you select from the menu of overloaded names. In Example 8-17 the overloaded function foo is called.

Example 8-17 Calling an Overloaded Function

(Ladebug) set $overloadmenu = 1
(Ladebug) call foo(15)
Enter the number of the overloaded function you want 
---------------------------------------------------- 
     1 void foo (const char *) 
     2 void foo (char *) 
     3 void foo (double) 
     4 void foo (float) 
     5 void foo (unsigned) 
     6 void foo (long) 
     7 void foo (short) 
     8 int foo (const double *) 
     9 int foo (int, float) 
    10 int foo (float*&) 
    11 int foo (const int&) 
    12 int foo (int&) 
    13 int foo (char) 
    14 int foo ( S *) 
    15 int foo ( S) 
    16 None of the above 
---------------------------------------------------- 
6
global foo (long):              15 
(Ladebug) 

8.12 Using Typecasts to Display Program Expressions

When debugging C++ programs, the debugger interprets casts as defined in The Annotated C++ Reference Manual. A cast has the following syntax:

(type) variable

The type is the type the debugger will use to interpret the program variable variable. The debugger does not allow cast conversion from an unsigned short type to a long int type.

In Example 8-18, a variable of type float is interpreted as an integer.

Example 8-18 Using a Cast to Perform Data Coercion

(Ladebug) whatis f
float f 
(Ladebug) print f
3.2 
(Ladebug) print (int)f
3 
(Ladebug) 

You can also use casts to interpret a base class object as a derived class object, or to interpret a derived class object as a base class object. In Example 8-19, the class derived inherits the public members of class base. A pointer to an object of class derived is declared to be a pointer to an object of class base. A cast is used to display the object's contents using the correct class type.

Example 8-19 Using Casts on a Derived Class Object

(Ladebug) whatis bvar
 base * bvar 
(Ladebug) whatis derived
class derived : base { 
  int i; 
  derived (void); 
  ~derived (void); 
  virtual int foo (void); 
} derived 
(Ladebug) whatis base
class base  { 
  int j; 
  base (void); 
  ~base (void); 
  virtual int foo (void); 
} base 
(Ladebug) print *bvar
class { 
        j = 0; 
    } 
(Ladebug) print *(derived *)bvar
class { 
        base = class { 
            j = 0; 
        }; 
        i = 4195376; 
    } 
(Ladebug) 

Example 8-20 shows how to use a type transfer to interpret a variable of type float as an integer.

Example 8-20 Using a Cast with Pointer Notation to Perform a Type Transfer

(Ladebug) print &f
0x11ffffe84 
(Ladebug) print *(int *)&f
1078774989 
(Ladebug) 

You can also perform the type transfer shown in this example by using C++ reference types. Example 8-21 shows how to use reference type notation to perform a type transfer.

Example 8-21 Using a Cast with Reference Type Notation to Perform a Type Transfer

(Ladebug) print &f
0x11ffffe84 
(Ladebug) print (int&)f
1078774989 
(Ladebug) 

8.13 Class Templates and Function Templates

The debugger provides support for debugging class templates and function templates in much the same way as other classes and functions in C++, with the limitations described in this section.

You can use the whatis command on an instantiation of the function template as shown in Example 8-22.

Example 8-22 Example of a Function Template

(Ladebug) list 1
      1 // remember to compile with -define_templates 
      2 template<class T> int compare(T t1, T t2) 
      3 { 
      4         if (t1 < t2) return 0; 
      5         else         return 1; 
      6 } 
      7 
      8 main() 
      9 { 
>    10         int i = compare(1,2); 
     11 } 
(Ladebug) whatis compare
int compare (int, int) 
(Ladebug) 

You can set a breakpoint in a template function as shown in Example 8-23.

Example 8-23 Setting a Breakpoint in the Template Function

(Ladebug) stop in compare
[#2: stop in compare(int, int) ] 
(Ladebug) run
[2] stopped at [compare(int, int):4 0x120000560]   
      4         if (t1 < t2) return 0; 
(Ladebug) 

As shown in Example 8-24, while inside the function template, you can set or ask for the current function context, and the instantiated function will be displayed.

Example 8-24 Displaying the Current Function Context for a Function Template

(Ladebug) func
compare(int, int) in c++functemp.C line No. 4: 
      4         if (t1 < t2) return 0; 
(Ladebug) 

For class templates, you cannot use the whatis command with the template name, but you can use the whatis command on a specific instantiation of the class template. This is the instantiated name that the debugger prints when it encounters variables of the template class type. Example 8-25 displays the class definition of a particular instantiation of a parameterized stack.

Example 8-25 Displaying an Instantiated Class Template

(Ladebug) list 1, 24
      1 #include <iostream.h> 
      2 
      3 template <class T, int size> class stack { 
      4         T s[size]; 
      5         int top; 
      6 public: 
      7         stack() { top = 0; } 
      8         void push(T item) 
      9              { 
     10               s[top++] = item; 
     11              } 
     12         T pop(); 
     13 }; 
     14 
     15 template<class T, int size> T stack<T,size>::pop() 
     16 { 
     17         return s[--top]; 
     18 } 
     19 
     20 stack<int,10*10> S; 
     21 stack<double,10> F; 
     22 
     23 #pragma define_template stack<int,100> 
     24 #pragma define_template stack<double,10> 
(Ladebug) whatis stack<int,100>
class stack<int,100>  { 
  array [subrange 0 ... 99 of int] of int s; 
  int top; 
  stack<int,100> (void); 
  void push (int); 
  int pop (void); 
} stack<int,100> 
(Ladebug) 

Similarly, as shown in Example 8-26, you can use the whatis S command. The instance of S is displayed as stack<int,100> rather than just S.

Example 8-26 Displaying an Instantiated Class Template

(Ladebug) whatis S
class stack<int,100>  { 
  array [subrange 0 ... 99 of int] of int s; 
  int top; 
  stack<int,100> (void); 
  void push (int); 
  int pop (void); 
} S 
(Ladebug) 

As shown in Example 8-27, you can set breakpoints in template functions and ask for the current function context while inside a template function.

Example 8-27 Setting Breakpoints in an Instantiated Class Function

(Ladebug) stop in S.pop
[#1: stop in stack<int,100>::pop(void) ] 
(Ladebug) run
stopped at [stack<int,100>::pop(void):17 0x120001e0c]  
     17         return s[--top]; 
(Ladebug) func
stack<int,100>::pop(void) in c++classtemp.C line No. 17: 
     17         return s[--top]; 
(Ladebug) print top
2 
(Ladebug) 

You can explicitly set your current class scope to a particular instantiation of a class template if you are not in the proper class scope. See Example 8-28 and Example 8-29.

Example 8-28 Setting Current Class Scope to an Instantiated Class

(Ladebug) stop in push
Symbol push not visible in current scope. 
push has no valid breakpoint address 
Warning: Breakpoint not set 
(Ladebug) class
Current context is not a class 
(Ladebug) class S
class stack<int,100>  { 
  array [subrange 0 ... 99 of int] of int s; 
  int top; 
  stack<int,100> (void); 
  ~stack<int,100> (void); 
  void push (int); 
  int pop (void); 
} 
(Ladebug) stop in push
[#4: stop in stack<int,100>::push(int) ] 
(Ladebug) run
[4] stopped at [stack<int,100>::push(int):10 0x120001cd0] 
     10               s[top++] = item; 
(Ladebug) 

Example 8-29 Alternate Method ofSetting Current Class Scope

(Ladebug) class stack<int,100>
class stack<int,100>  { 
  array [subrange 0 ... 99 of int] of int s; 
  int top; 
  stack<int,100> (void); 
  ~stack<int,100> (void); 
  void push (int); 
  int pop (void); 
} 
(Ladebug) stop in push
[#5: stop in stack<int,100>::push(int) ] 
(Ladebug) 

Additional limitations for debugging templates include:


Previous Next Contents Index