This chapter describes how dbx handles C++ exceptions and debugging C++ templates, including a summary of commands used when completing these tasks and examples with code samples.
This chapter is organized into the following sections:
For information on compiling C++ programs, see "Debugging Optimized Code".
Although this chapter concentrates on two specific aspects of debugging C++, dbx does allow you full functionality when debugging your C++ programs. You can:
Find out about class definitions
Print or display inherited data members
Find out dynamic information about an object pointer
Find out information about debugging virtual functions
Using runtime type information
Set breakpoints on all member functions of a class
Set breakpoints on all overloaded member functions
Set breakpoints on all overloaded non-member functions
Deal with overloaded functions/data members
Set breakpoints on all member functions of a particular object
For more information on any of these topics, please look in the index under C++.
A program stops running if an exception occurs. Exceptions signal programming anomalies, such as division by zero or array overflow. To deal with exceptions, you can set up blocks to catch exceptions raised by expressions elsewhere in the code.
While debugging a program, dbx enables you to:
Catch unhandled exceptions before stack unwinding
Catch unexpected exceptions
Catch specific exceptions whether handled or not before stack unwinding
Determine where a specific throw would be caught if it occurred at a particular point in the program
If you step after stopping at a throw point, control is returned at the start of the first destructor executed during stack unwinding. If you step out of a destructor executed during stack unwinding, control is returned at the start of the next destructor. When all destructors have been executed, step brings you to the catch block handling the throw.
Use this command to display an exception's type. This variable can be used at any time during debugging. With --d, the derived type is shown; otherwise, the static type is shown. This command overwrites the dbxenv variable output_dynamic_type setting.
You can intercept, or catch, exceptions of a specific type before the stack has been unwound. Use this command with no arguments to list the types that are being intercepted. Use --a to intercepted all throws. Use typename to add a type to the intercept list. Use --x to exclude a particular type from being intercepted.
For example, to intercept all types except int, you could enter:
(dbx) intercept -a (dbx) intercept -x int
Use this command to remove exception types from the intercept list. Use this command with no arguments to list the types that are being intercepted (same as intercept). Use --a to remove all intercepted types from the list. Use typename to remove a type from the intercept list. Use --x to stop excluding a particular type from being intercepted.
This command reports where, if at all, an exception of typename would be caught if thrown at the current point of execution. Use this command to find out what would happen if an exception were thrown from the top frame of the stack.
The line number, function name, and frame number of the catch clause that would catch typename is displayed.
This example demonstrates how exception handling is done in dbx using a sample program containing exceptions. An exception of type int is thrown in the function bar and is caught in the following catch block.
1 #include <stdio.h> 2 3 class c { 4 int x; 5 public: 6 c(int i) { x = i; } 7 ~c() { 8 printf("destructor for c(%d)\n", x); 9 } 10 };
11 12 void bar() { 13 c c1(3); 14 throw(99); 15 } 16 17 int main() { 18 try { 19 c c2(5); 20 bar(); 21 return 0; 22 } 23 catch (int i) { 24 printf("caught exception %d\n", i); 25 } 26 }
The following transcript from the example program shows the exception handling features in dbx.
(dbx) intercept (dbx) intercept int int (dbx) stop in bar (2) stop in bar() (dbx)run Running: a.out (process id 304) Stopped in bar at line 13 in file "foo.cc" 13 c c1(3); (dbx) whocatches int int is caught at line 24, in function main (frame number 2) (dbx) whocatches c dbx: no runtime type info for class c (never thrown or caught) (dbx) contException of type int is caught at line 24, in function main (frame number 4) stopped in _exdbg_notify_of_throw at 0xef731494 0xef731494: _exdbg_notify_of_throw : jmp %o7 + 0x8 Current function is bar 14 throw(99);
(dbx) step stopped in c::~c at line 8 in file "foo.cc" 8 printf("destructor for c(%d)\n", x); (dbx) step destructor for c(3) stopped in c::~c at line 9 in file "foo.cc" 9 } (dbx) step stopped in c::~c at line 8 in file "foo.cc" 8 printf("destructor for c(%d)\n", x); (dbx) step destructor for c(5) stopped in c::~c at line 9 in file "foo.cc" 9 ) (dbx) step stopped in main at line 24 in file "foo.cc" 24 printf("caught exception %d\n", i); (dbx) step caught exception 99 stopped in main at line 26 in file "foo.cc" 26 }
dbx supports C++ templates. You can load programs containing class and function templates into dbx and invoke any of the dbx commands on a template that you would use on a class or function, such as:
Setting breakpoints at class or function template instantiations
Printing a list of all class and function template instantiations
Displaying the definitions of templates and instances
Calling member template functions and function template instantiations
Printing values of function template instantiations
Displaying the source code for function template instantiations
The following code example shows the class template Array and its instantiations and the function template square and its instantiations.
In the following example:
Array is a class template
square is a function template
Array<int> is a class template instantiation (template class)
Array<int>::getlength is a member function of a template class
square(int, int*) and square(double, double*) are function template instantiations (template functions)
1 template<class C> void square(C num, C *result 2 { 3 *result = num * num; 4 } 5 6 template<class T> class Array 7 { 8 public: 9 int getlength(void) 10 { 11 return length; 12 } 13 14 T & operator[](int i) 15 { 16 return array[i]; 17 } 18 19 Array(int l) 20 { 21 length = l; 22 array = new T[length]; 23 } 24 25 ~Array(void) 26 { 27 delete [] array; 28 } 29 30 private: 31 int length; 32 T *array; 33 }; 34
35 int main(void) 36 { 37 int i, j = 3; 38 square(j, &i); 39 40 double d, e = 4.1; 41 square(e, &d); 42 43 Array<int> iarray(5); 44 for (i = 0; i < iarray.getlength(); ++i) 45 { 46 iarray[i] = i; 47 } 48 49 Array<double> darray(5); 50 for (i = 0; i < iarray.getlength(); ++i) 51 { 52 iarray[i] = i * 2.1; 53 } 54 55 return 0; 56 }
You can invoke any of these exception handling commands when debugging a program.
Use these commands on templates and template instantiations. Once you know the class or type definitions, you can print values, display source listings, or set breakpoints.
Use whereis to print a list of all occurrences of function or class instantiations for a function or class template.
(dbx) whereis Array class template instance: a.out`Array<int> class template instance: a.out`Array<double> class template: a.out`template_doc_2.cc`Array
(dbx) whereis square function template instance: a.out`square(double, double*) function template instance: a.out`square(int, int*) function template: a.out`square
Use whatis to print the definitions of function and class templates and instantiated functions and classes
(dbx) whatis Array template<class T> class Array To get the full template declaration, try `whatis -t Array<int>';
(dbx) whatis square More than one identifier `square'. Select one of the following names: 0) Cancel 1) function template instance: `square(int, int*) 2) function template instance: `square(double, double*) 3) `a.out`square > 3 template<class C> void square(C num, C *result);
For a class template instantiation:
(dbx) whatis -t Array<double> class Array<double>; { public: int Array<double>::getlength() double &Array<double>::operator [](int i); Array<double>::Array<double>(int l); Array<double>::~Array<double>(); private: int length; double *array; };
For a function template instantiation:
(dbx) whatis square(int, int*)void square(int num, int *result);
To stop in all member functions of a template class:
(dbx)stop inclass Array (2) stop inclass Array
Use stop inclass to set breakpoints at all member functions of a particular template class:
(dbx) stop inclass Array<int> (2) stop inclass Array<int>
Use stop infunction to set breakpoints at all instances of the specified function template:
(dbx) stop infunction square (9) stop infunction square
Use stop in to set a breakpoint at a member function of a template class or at a template function.
For a class template instantiation:
(dbx) stop in Array<int>::Array<int>(int l) (2) stop in Array<int>::Array<int>(int)
(dbx) stop in square(double, double*) (6) stop in square(double, double*)
Use call to explicitly call a function instantiation or a member function of a class template, provided you are stopped in scope. If dbx is unable to choose the correct instance, a menu allows you to choose the correct instance.
(dbx) call square(j,&i)
Use print to evaluate a function instantiation or a member function of a class template:
(dbx) print iarray.getlength() iarray.getlength() = 5
Use print to evaluate the this pointer:
(dbx) whatis this class Array<int> *this; (dbx) print *this *this = { length = 5 array = 0x21608 }
Use list to print the source listing for the specified function instantiation:
(dbx) list square(int, int*)