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 Compiling a Program for Debugging.
Although this chapter concentrates on two specific aspects of debugging C++, dbx allows you full functionality when debugging your C++ programs. You can:
Find out about class and type definitions (see Looking Up Definitions of Types and Classes)
Print or display inherited data members (see Printing C++)
Find out dynamic information about an object pointer (see Printing C++)
Debug virtual functions (see Calling a Function)
Using runtime type information (see Printing the Value of a Variable, Expression, or Identifier)
Set breakpoints on all member functions of a class (see Setting Breakpoints in Member Functions of the Same Class)
Set breakpoints on all overloaded member functions (see Setting Breakpoints in Member Functions of Different Classes)
Set breakpoints on all overloaded nonmember functions (see Setting Multiple Breakpoints in Nonmember Functions)
Set breakpoints on all member functions of a particular object (see Setting Breakpoints in Objects)
Deal with overloaded functions or data members (see Setting a stop Breakpoint in a Function)
A program stops running if an exception occurs. Exceptions signal programming anomalies, such as division by zero or array overflow. 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 exception would be caught if it occurred at a particular point in the program
If you give a step command after stopping at a point where an exception is thrown, 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, a step command brings you to the catch block handling the throwing of the exception.
Use the exception command to display an exception’s type at any time during debugging. If you use the exception command without an option, the type shown is determined by the setting of the dbx environment variable output_dynamic_type:
If it is set to on, the derived type is shown.
If it is set to off (the default), the static type is shown.
Specifying the -d or +d option overrides the setting of the environment variable:
If you specify -d, the derived type is shown.
If you specify +d, the static type is shown.
For more information, see exception Command.
You can intercept, or catch, exceptions of a specific type before the stack has been unwound. Use the intercept command with no arguments to list the types that are being intercepted. Use -all to intercept all exceptions. Use typename to add a type to the intercept list. Use -x to exclude a particular type to the excluded list to keep it from being intercepted. Use -set to clear both the intercept list and the excluded list, and set the lists to intercept or exclude only throws of the specified types
For example, to intercept all types except int, you could type:
(dbx) intercept -all -x int |
To intercept exceptions of type Error, you would type:
(dbx) intercept Error |
After intercepting too many CommonError exceptions, you could exclude these exceptions by typing:
(dbx) intercept -x CommonError |
Typing the intercept command with no arguments would then show that the intercept list includes unhandled exceptions and unexpected exceptions, which are intercepted by default, plus exceptions of class Error except for those of class CommonError.
(dbx) intercept -unhandled -unexpected class Error -x class CommonError |
If you then realize that Error is not the class of exceptions that interests you, but you do not know the name of the exception class you are looking for, you could try intercepting all exceptions except those of class Error by typing
(dbx) intercept -all -x Error |
For more information, see intercept Command.
Use the unintercept command to remove exception types from the intercept list or the excluded list. Use the command with no arguments to list the types that are being intercepted (same as the intercept command). Use -all to remove all types from the intercept list. Use typename to remove a type from the intercept list. Use -x to remove a type from the excluded list.
For more information, see unintercept Command.
The whocatches command reports where 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 are displayed. The command returns “type is unhandled” if the catch point is in the same function that is doing the throw.
For more information, see whocatches Command.
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 -unhandled -unexpected (dbx) intercept int <dbx> intercept -unhandled -unexpected 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) cont Exception 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 (see stop inclass classname Command, stop infunction name Command, and stop in function Command)
Printing a list of all class and function template instantiations (see whereis name Command)
Displaying the definitions of templates and instances (see whatis name Command)
Calling member template functions and function template instantiations (see call function_name(parameters) Command)
Printing values of function template instantiations (print Expressions)
Displaying the source code for function template instantiations (see list Expressions)
The following code example shows the class template Array and its instantiations and the function template square and its instantiations.
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 < darray.getlength(); ++i) 51 { 52 darray[i] = i * 2.1; 53 } 54 55 return 0; 56 } |
In the 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)
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 the whereis command to print a list of all occurrences of function or class instantiations for a function or class template.
For a class template:
(dbx) whereis Array member function: `Array<int>::Array(int) member function: `Array<double>::Array(int) class template instance: `Array<int> class template instance: `Array<double> class template: `a.out`template_doc_2.cc`Array |
For a function template:
(dbx) whereis square function template instance: `square<int>(__type_0,__type_0*) function template instance: `square<double>(__type_0,__type_0*) |
The __type_0 parameter refers to the 0th template parameter. A __type_1 would refer to the next template parameter.
For more information, see whereis Command.
Use the whatis command to print the definitions of function and class templates and instantiated functions and classes.
For a class template:
(dbx) whatis -t Array template<class T> class Array To get the full template declaration, try `whatis -t Array<int>’; |
For the class template’s constructors:
(dbx) whatis Array More than one identifier ’Array’. Select one of the following: 0) Cancel 1) Array<int>::Array(int) 2) Array<double>::Array(int> > 1 Array<int>::Array(int 1); |
For a function template:
(dbx) whatis square More than one identifier ’square’. Select one of the following: 0) Cancel 1) square<int(__type_0,__type_0*) 2) square<double>(__type_0,__type_0*) > 2 void square<double>(double num, double *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); |
For more information, see whatis Command.
To stop in all member functions of a template class:
(dbx)stop inclass Array (2) stop inclass Array |
Use the stop inclass command to set breakpoints at all member functions of a particular template class:
(dbx) stop inclass Array<int> (2) stop inclass Array<int> |
For more information, see stop Command and inclass classname [-recurse | -norecurse].
Use the stop infunction command to set breakpoints at all instances of the specified function template:
(dbx) stop infunction square (9) stop infunction square |
For more information, see stop Command and infunction function.
Use the stop in command to set a breakpoint at a member function of a template class or at a template function.
For a member of a class template instantiation:
(dbx) stop in Array<int>::Array(int l) (2) stop in Array<int>::Array(int) |
For a function instantiation:
(dbx) stop in square(double, double*) (6) stop in square(double, double*) |
For more information, stop Command and in function.
Use the call command to explicitly call a function instantiation or a member function of a class template when you are stopped in scope. If dbx is unable to determine the correct instance, it displays a numbered list of instances from which you can choose.
(dbx) call square(j,&i) |
For more information, see call Command.
Use the print command 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 } |
For more information, see print Command.
Use the list command to print the source listing for the specified function instantiation.
(dbx) list square(int, int*) |
For more information, see list Command.