Friday, March 23, 2007

Debugging Memory Value Meanings

The Visual Studio compiler automatically assigns default values to certain types of variables depending on how they were declared (stack based vs heap based) and what types of variables they are (pointers etc). These values become very useful during debugging because you can tell what went wrong when an exception is thrown. Here are some common values and their meanings:

  • 0xfeeefeee - Memory reserved to heap allocation but has not been allocated yet
  • 0xcdcdcdcd - Uninitialized heap variable (Think of the "C" as Clean memory)
  • 0xcccccccc -Uninitialized stack variable (Think of the "C" as Clean memory)
  • 0xfdfdfdfd - Padding around an array (Think of the "F" as Fences around your variable)
  • 0xdddddddd - Released heap variable (delete or free) (Think of the "D" as in Dead)

Friday, March 16, 2007

C++ Objects Part 6: Ambiguous Base Classes

An ambiguous base class is a base class that is included in a derived class twice. Because you can't just derive from a class twice, this usually happens by having parent classes who both derive from the same class without virtualizing that common base.

The storage implications of ambiguous base classes are relatively simple. Because each parent class's memory layout contains the base, we know where the two bases will be in memory - we simply apply our pattern for inheritance via containment recursively.

class R { };
class B1 : public R { };
class B2 : public R { };
class D : public B1, public B2 { };

gives us

struct R {
vtable * vt;

struct B1 {
R base;

struct B2 {
R base;

struct D {
B1 base;
B2 base;

Thus we have two instance of R: obj.base1.base and obj.base2.base reference each copy of R.

Static casts are casts that can be computed knowing only compile-time information - that is, casts that don't require knowing the full class of the casted object.

A static cast from D to R is illegal because it is ambiguous. Do we want R via B1 or B2? We don't know, and because the cast is static the compiler knows we don't know at compile time and generates an error.

If you cast to B1 first and then R it is legal - you have disambiguated. (This should not be surprising - if we simply had an object of type B1, casting to R would work! Remember, memory layout doesn't change with type!)

Static casts give us compile-time checking of all casts for ambiguity - we always know what we are getting. Next I'll cover dynamic casts and ambiguous base classes, which are more complex.