Chapter Contents

Previous

Next
Debugging C++ Programs

Specifying C++ Function Names

One of the unique features of the SAS/C C++ Development System is that the debugger accepts and understands C++ function names, including multitoken and overloaded function names. This section describes how to specify C++ function names in debugger commands.

If you are specifying a nonoverloaded, single-token function name in a debugger command, you do not have to do anything differently from when you are specifying a C function name. For example, you could issue the following command:

break func1 entry

There are additional rules, however, for specifying multitoken C++ function names and overloaded function names in debugger commands. This section also explains how to specify member function names and file-scope function names.

The rules for specifying constructor and destructor function names are unique to these types of functions and are covered separately. See Functions in a Mix of C and C++ Code for information on how the debugger handles function names when you mix C and C++ code. Also, see Translator-Generated Functions for information on how the debugger handles translator-generated functions (such as assignment operators and copy constructors).


Multitoken Function Names

Multitoken function names are function names that are not only a C++ identifier, but that contain other items such as the scope operator (::) or two-word function names such as operator and conversion functions. Here are some examples of multitoken C++ function names:

When you specify a multitoken C++ function name in a debugger command, the function name must be enclosed in double quotes. Here is an example of the break command and a multitoken function name. This command specifies to break at the entry to member function func1 in class ABC :

break "ABC::func1" entry

Spaces around tokens that are not identifiers are optional.


Overloaded Function Names

One of the things that sets C++ apart from C is that C++ supports overloaded functions. However, overloaded functions present a challenge for the debugger because the debugger has to determine which function you want to access.

When you specify an overloaded function name in a debugger command, you are presented with a numbered list of C++ function names with arguments. Determine which number represents the function you want to access, and reissue the debugger command by appending a parenthesized number after the function name. For example, suppose you have the following three constructors declared in class myclass , in this order:

myclass(char);
myclass(short);
myclass(long);

If you issue a break "myclass::myclass" entry command, the debugger shows you the following list:

1  myclass::myclass(char)
2  myclass::myclass(short)
3  myclass::myclass(long)

You can place a breakpoint on entry to the constructor that takes a short integer by specifying the following break command:

break "myclass::myclass"(2) entry

As long as you do not relink your program, the subscript numbers for overloaded functions remain the same. For example, you can define a debugger macro or alias using the subscripts and use it throughout your debugging session.

Instead of choosing a particular number, you can specify that the command apply to all instances of the function by using 0 as the parenthesized number. For example, the following command sets breakpoints on entry to any myfunc function in class myclass , regardless of the argument type:

break "myclass::myfunc"(0) entry

However, a subscript of 0 is valid only at entry hooks, return hooks, call hooks, or * (that is, all line hooks). The only commands that permit a subscript of 0 are break, trace, ignore, runto , and on .

See "Interpreting C++ Demangled Names" in the SAS/C C++ Development System User's Guide for more information on interpreting the overloaded function names.


File-Scope and Member Functions

The debugger uses the scope operator (::) to determine if you want to access either a filescope or a member function.

If you have declared both a filescope myfunc and a member function myfunc in class ABC , use the scope operator to tell the debugger which function you mean when you issue debugger commands as follows:

"::myfunc"
refers to a file-scope function of name myfunc .

"ABC::myfunc"
refers to a member function of name myfunc in class ABC .

If you have only a file-scope function named myfunc , or only one member function named myfunc (but not both a file-scope function and a member function), you can omit the scope operator and specify only the function name in the debugger command.

Note:    If the debugger is stopped in a member function when you issue a debugger command that includes only the function name (and no scope operator), the command works as though the debugger were not stopped in a member function. That is, the debugger does not automatically prefix the function name with the class name of the class whose member function you are stopped in. This is slightly different from the behavior for data objects, in which the class name is automatically prefixed. See Searching for Data Objects.  [cautionend]


Constructors and Destructors

When you specify a constructor or destructor in a debugger command, it must be in one of the following two forms:

"
class-name::class-name

"

indicates a constructor.

"
class-name::~class-name

"

indicates a destructor.

Here is an example of setting a breakpoint on entry to the destructor for class ABC :

break "ABC::~ABC" entry


Functions in a Mix of C and C++ Code

If your load module contains at least one C++ compilation, your load module also contains a list of all function names that are visible to C++ compilations. If you issue a debugger command that refers to a function name that is not in this list, the debugger issues a warning message and assumes the function is a C function.

For example, suppose you have the following construct, in which a() is a C++ function and b() and c() are C functions:

a() calls b() calls c()

There is a function prototype for b() in the compilation containing a() . Because b() is visible to a C++ compilation, it is contained in the debugger's list of visible function names. Because no function prototype for c() is visible in any C++ compilation, c() is not contained in the list of function names that are visible to the debugger. If you use c() in a debugger command (such as in a break command), the debugger issues a message that it cannot resolve the function name by using the debugger file. The debugger assumes that c() is a C function.

Note:    If you see the warning message about unresolved function names yet you know that your program consists of only C++ functions, check the spelling of function names in your debugger commands.  [cautionend]


Translator-Generated Functions

The translator creates a number of functions automatically. These functions are required by the C++ language and follow the usual C++ rules. The functions that the translator may create include constructors, copy constructors, assignment operators, and destructors. The translator creates such a function when there is not a user-defined version of the function. The list of overloaded constructors that is displayed by the debugger when you issue a debugger command may include a translator-generated constructor as well as the user-defined constructors.

The following list shows the declarations for translator-generated functions:

class::class()

is the default constructor for class class . This constructor is called whenever an object of type class is defined without an explicit initializer.

class::class(const|volatile  class&)

is the default copy constructor for class class . A default copy constructor is created for any class , struct , or union that does not have a user-defined copy constructor. The copy constructor is called to initialize an object of type class with another object of the same class. The presence of const or volatile depends on the characteristics of the class.

class& class::operator=(const|volatile class&)

is the default assignment operator. This operator is called when an object of type class has an object assigned to it. The presence of const or volatile depends on the characteristics of the class.

class::~class()

is the default destructor. This destructor is called when an object of type class goes out of scope.

You may occasionally step into one of these translator-generated functions as you debug your code. When this happens, the Source window displays the source text at the class definition and the Status window displays the function name.


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.