Displaying Static and Dynamic Type Information

When displaying object information for C++ class pointers or references, you have the option of viewing either static type information or dynamic type information.

The static type of a class pointer or reference is its type as defined in the source code, and thus cannot change. The dynamic type is the type of the object being referenced, before any casts were made to that object, and thus may change during program execution.

The debugger provides a debugger variable, $usedynamictypes, which allows you to control which form of the type information is displayed. The default value for this variable is true (1), which indicates that the dynamic type information is displayed. Setting this variable to false (0) instructs the debugger to display static type information. The output of the print, and whatis commands are affected.

The display of dynamic type information is supported for C++ class pointers and references. All other types display static type information. In addition, if the dynamic type of an object cannot be determined, the debugger defaults to the use of static type information.

This debugger functionality does not relax the C++ visibility rules regarding object member access through a pointer/reference (only members of the static type are accessible). For more information about the C++ visibility rules, see The Annotated C++ Reference Manual (by Margaret E. Ellis and Bjarne Stroustrup, 1990, Addison-Wesley Publishing Company).

In order for dynamic type information to be displayed, the object's static type must have at least one virtual function defined as part of its interface (either one it introduced or one it inherited from a base class). If no virtual functions are present for an object, only the static type information for that object is available for display.

The following example shows debugger output with $usedynamictypes set to 0 (false):

(idb) print $usedynamictypes

0

(idb) whatis *this

class HeavenlyBody {

  const char* const _name;

  class HeavenlyBody* _innerNeighbor;

  class HeavenlyBody* _outerNeighbor;

  class HeavenlyBody* _firstSatellite;

  class HeavenlyBody* _lastSatellite;

  virtual void printBody(const class HeavenlyBody*, unsigned int);

  void printBodyAndItsSatellites(unsigned int) const;

  HeavenlyBody(char*);

  void addSatellite(class HeavenlyBody*);

  const char* name(void) const;

  unsigned int satelliteNumber(class HeavenlyBody*) const;

}

(idb) print *this

class HeavenlyBody {

  _name = 0x805abe4="Moon";

  _innerNeighbor = 0x0;

  _outerNeighbor = 0x0;

  _firstSatellite = 0x0;

  _lastSatellite = 0x0;

}

The following example displays debugger output with $usedynamictypes set to 1 (true). The output is for the same object as the previous example, at the same point in program execution:

(idb) print $usedynamictypes

1

(idb) whatis *this

class Moon : Planet {

  const Kilometers _radius;

  Moon(char*, Megameters, Kilometers, class Planet*);

  Kilometers radius(void) const;

  virtual void printBody(unsigned int) const;

  virtual ~Moon(void);

}

(idb) print *this

class Moon {

  _radius = 1738;

  _name = 0x805abe4="Moon";       // class Planet::HeavenlyBody

  _innerNeighbor = 0x0;           // class Planet::HeavenlyBody

  _outerNeighbor = 0x0;           // class Planet::HeavenlyBody

  _firstSatellite = 0x0;          // class Planet::HeavenlyBody

  _lastSatellite = 0x0;           // class Planet::HeavenlyBody

  _primary = 0x806b4e0;           // class Planet::Orbit

  _distance = 384;                // class Planet::Orbit

  _name = 0x806b5c0="Earth 1";    // class Planet::Orbit

}