This is why you must initialize your objects before using them

Q I have two views. One view needs to check if the other view has been instantiated yet—that is, if the pointer to it is valid. How do I test a pointer to see if it points to a valid class in memory? I tried setting the pointer to NULL, then checking to see if it was still NULL, but the pointer has the value 0xCDCDCDCD before it is instantiated. Will it always have this value before instantiation? Can I just check for 0xCDCDCDCD? Where did this value come from?

Jay Sanbar

A 0xCDCDCDCD is a debugging value that comes from the bowels of the C runtime library. When you allocate a block of memory in a debug build, it’s initialized to this spurious value in the hope of catching bugs. 0xCDCDCDCD is non-NULL and is never a valid memory pointer.
In the old days (I don’t remember exactly when), MFC did this initialization itself. Now the C runtime library does it, so non-MFC programs can benefit too. It took me some time to track the code and find out exactly where this initialization occurs. You wouldn’t believe how many different ::new operators there are!
During my spelunking, I found an amusing conundrum in the code included with Visual C++ 5.0 (which has been corrected in Visual C++ 6.0). In the comments for the function _set_new_handler, the following text appears: “WARNING: This function is OBSOLETE. Use set_new_ handler instead.” When I went to set_new_handler, I found another comment: “WARNING: set_new_handler is a stub function that is provided to allow compilation of the Standard Template Library (STL). Do NOT use it to register a new handler. Use _set_new_handler instead.” Well, which is it? It just goes to show how much trouble most programmers have keeping their comments up-to-date!
But to return to the topic at hand: where does 0xCDCDCDCD get filled in? In debug builds, DEBUG_NEW is #defined to an overloaded new operator that has file name and line number arguments.

 #define DEBUG_NEW new(THIS_FILE, __LINE__)
If your allocation chomps, you get a friendly message like, “You lose: file foo.cpp, line 345. Try again tomorrow.”
Aside from displaying a message if the allocation croaks, the DEBUG_NEW version of ::new calls another function, _nh_malloc_dbg (new handler malloc debug) to allocate your block. There are almost as many varieties of malloc as there are ::new operators: malloc, malloc_dbg, malloc_crt. And there are_nh varieties for all. The one used in this case is _nh_malloc_dbg, which calls yet another malloc function, _heap_alloc_dbg. This one actually allocates the memory. And since it’s the debug version (that little dbg at the end of the name gives it away), _heap_alloc_dbg initializes each byte of the allocated block to 0xCD. It also initializes the “no-man’s land”—extra bytes that belong to the internal block allocated, but not the block you requested—with 0xFD. (The internal block can be larger than what you requested.) Similarly, the debug version of free called from ::delete initializes freed bytes with yet another special value, 0xDD. Figure 1 is a snippet from the C runtime source file dbgheap.c that explains why Microsoft chose these particular values.
Using bogus values to initialize allocated and freed memory helps you discover bugs since the values are unlikely to be anything that makes sense to your program. In the case of freed memory, freed blocks were not meant to retain their content. Suppose you have two pointers, p1 and p2, that point to the same string, “hello, world”. You delete p1. Now the other pointer, p2, is invalid too. Since the runtime library fills the string with 0xDD, it’s likely you’ll discover the bug if your program ever tries to use p2. So filling freed bytes with 0xDD helps you find a whole class of bugs where you attempt to go on using a block after you’ve freed it.
When you switch to your release build, allocated memory is not initialized. The contents of an allocated block in a release build are random; freed blocks retain their contents. In the example just mentioned, p1 will keep its contents, “hello, world”, even after you delete it, until the block is reused by some other part of your program.
So now that you understand where 0xCDCDCDCD comes from, how do you solve your problem? Easy. If you want your pointer to start out NULL, all you have to do is initialize it to NULL in your constructor.
 class CMyView1 : public CView {
     class CMyView2* m_pOtherView;
 •
 •
 •
 };
 CMyView1::CMyView1() : m_pOtherView(NULL)
 {
 •
 •
 •
 }
It’s also OK to use an assignment within the body of the constructor.
 CMyView1::CMyView1()
 {
     m_pOtherView = NULL;
 •
 •
 •
 }
Some programmers prefer the first method (member initializer in the function header) because it eliminates redundant initializations. This isn’t important for primitive objects like pointers.
But suppose instead of a pointer m_pOtherView, you had an object m_x of class X. Writing m_x = NULL in the body of the constructor is inefficient because C++ will first call the default constructor X::X to initialize m_x before your assignment m_x = NULL is executed. If you write m_ x(NULL) as a member initializer in the function header, m_x gets initialized only once. The member initializer is also the only way to initialize a member that’s a reference, since you can’t assign a reference, you can only initialize it. (Assigning a reference alters the object referred to, not the reference itself.) For primitive objects like ints, longs, pointers, and so on, the member initializer and assignment-within-constructor result in code that is for all practical purposes identical, assuming you put the assignments in the order the members are declared and before any other statements in the constructor body.
The C runtime special initializations don’t happen for stack objects, so you should never rely on the special values—that is, test for 0xCDCDCDCD. Stack objects are initialized with random data—whatever happens to be on the stack at the time. That’s why it’s important to always initialize all class members in your constructors.
Once you initialize m_pOtherView to NULL, checking for a valid view is as simple as checking for NULL.
 if (m_pOtherView != NULL) {
     // m_pOtherView is valid
 •
 •
 •
 }
Of course, this assumes that your code is perfect, and that you only assign m_pOtherView to a view of the right type (CMyView2). In the interests of protecting yourself against your errant half, it’s a good idea to add an ASSERT check.
 if (m_pOtherView != NULL) {
     // m_pOtherView is valid
     ASSERT_VALID(m_pOtherView);
     ASSERT_KINDOF(CMyView2, m_pOtherView);
 •
 •
 •
 }
ASSERT_VALID is an MFC macro that calls AfxAssertValidObject. Figure 2 shows the highlights from this useful function. AfxAssertValidObject checks the validity of your object itself and its vtable by calling another function, AfxIsValidAddress. (AfxAssertValidObject assumes pOb is a pointer to an object of class derived from CObject.)
 BOOL AfxIsValidAddress(const void* lp,
                        UINT nBytes, BOOL bReadWrite)
 {
     // simple version using Win-32 APIs for pointer
     // validation.
     return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
         (!bReadWrite || !IsBadWritePtr((LPVOID)lp,
                                        nBytes)));
 }
IsBadReadPtr and IsBadWritePtr test whether a given address/size represents a valid block of readable or writable memory for the calling process. These functions know how Windows® allocates memory internally, so they’re good at finding bad pointers. By default, AfxAssertValidObject calls AfxIsValidAddress with FALSE as the third argument, so it checks that the memory is readable. If you know you intend to write into a block of memory, you could play it really safe by #defining a macro ASSERT_WRITABLE(pOb) that calls AfxIsValidAddress with TRUE as the third argument. Of course, if you try to write into nonwritable memory, you’ll find out soon enough!
Once your object pointer passes the Win32® validity test, AfxAssertValidObject calls pOb->AssertValid. Most of you are familiar with AssertValid; it’s the virtual function you write to check that your object is shipshape. You can put any checks you want in AssertValid, including none at all if you’re lazy like me. (I like to live dangerously.) If you do write an AssertValid function, even an empty one, make sure you call the base class AssertValid so you benefit from its checks too.
 void CMyView::AssertValid() const
 {
     CView::AssertValid();
 }
You might think there’s nothing more to say about Jay’s question, which I could have answered in a single sentence: initialize your pointer to NULL in the constructor. But things have only started to get interesting! The second check I recommended you add, ASSERT_KINDOF(CMyView2, m_pOtherView), opens a whole other C++/MFC subject: how do you tell if a given pointer points to an object of a particular type? There are many ways. MFC uses ASSERT_KINDOF and DYNAMIC_DOWNCAST, and C++ employs dynamic_cast.
The MFC macros all use the MFC CRuntimeClass structure to uniquely identify each class in your program. The CRuntimeClass for a class gets declared/defined when you use the DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC macros or their relatives DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE and DECLARE_SERIAL/IMPLEMENT_SERIAL. Such classes must be derived from CObject, the mother of all MFC runtime classes. CObject has a function, IsKindOf, that tests whether a pointer points to an object of a given class—that is, a given CRuntimeClass.
 BOOL bIsFoo = pFoo->IsKindOf(RUNTIME_CLASS(CFoo));
ASSERT_KINDOF is a macro that wraps such a test inside an ASSERT statement. If you use ASSERT_KINDOF, it’s a good idea to precede it with ASSERT_VALID, as I did in the previous example, because ASSERT_KINDOF does not check the pointer first. It simply calls p->IsKindOf. So if p is NULL or some other invalid pointer, the ASSERT_ KINDOF will crash and you may get confused. If you perform such checks frequently, you might want to write a macro ASSERT_VALID_KINDOF that does ASSERT_ VALID and ASSERT_KINDOF.
Another way to accomplish more or less the same thing as ASSERT_KINDOF is to use STATIC_DOWNCAST.
 CFoo* pFoo = STATIC_DOWNCAST(CFoo, p);
STATIC_DOWNCAST generates a call to AfxStaticDownCast, which looks like this:
 CObject* AfxStaticDownCast(CRuntimeClass* pClass,
     CObject* pObject)
 {
     ASSERT(pObject == NULL ||
            pObject >IsKindOf(pClass));
     return pObject;
 }
STATIC_DOWNCAST only expands to AfxStaticDownCast in a debug build; when you create a release build, STATIC_DOWNCAST expands to a normal C++ cast—that is, nothing.
 CFoo* pFoo = (CFoo*)p;
So STATIC_DOWNCAST is in effect a shorthand way of doing ASSERT_KINDOF before you do a C++ cast. As with ASSERT_KINDOF, you should use ASSERT_VALID first, or write a new macro ASSERT_STATIC_DOWNCAST. In general, it’s a good thing to use STATIC_DOWNCAST whenever you cast from one CObject pointer to another—you expect the cast to succeed, but you want to add an ASSERT just to be sure.
If the cast can legitimately fail, there is another macro to use: DYNAMIC_DOWNCAST. DYNAMIC_DOWNCAST is like STATIC_DOWNCAST, but you use it when you want to perform a cast in release as well as debug builds—that is, when it is legitimate for your cast to fail. Whereas STATIC_ DOWNCAST generates a type check in debug builds only, DYNAMIC_DOWNCAST generates a type check in both debug and release builds. And while the STATIC version bombs if the type check fails, DYNAMIC_DOWNCAST simply returns NULL. DYNAMIC_DOWNCAST invokes AfxDynamicDownCast to do the work:
 CObject* AfxDynamicDownCast(CRuntimeClass* pClass,
                             CObject* pObject)
 {
     if (pObject != NULL && pObject->IsKindOf(pClass))
         return pObject;
     else
         return NULL;
 }
This is how to use it in your program:
 CFoo* pFoo = DYNAMIC_DOWNCAST(CFoo, p);
 if (pFoo) {
     // Yes, pFoo points to a CFoo
 } else {
     // No, pFoo doesn't point to a CFoo
 }
These two macros are called DOWNCASTs because in both cases you are casting a pointer to a CObject down the inheritance hierarchy to a pointer to some other CObject-derived class.
STATIC_DOWNCAST and DYNAMIC_DOWNCAST only work with the MFC runtime class system rooted in CObject. What if you want to use the same sort of checking with non-MFC classes? There is a way. STATIC_DOWNCAST and DYNAMIC_DOWNCAST are modeled after the C++ casting operators static_cast and dynamic_cast, which are relatively recent additions to the C++ language. They work much the same as their MFC counterparts, except that STATIC_DOWNCAST in MFC has an ASSERT check built into it, while static_cast in C++ has no such bulletproofing. Also, the syntax is different.
 CFoo* pFoo = static_cast<CFoo*>p;
The previous line of code is more or less the same as writing:
 CFoo* pFoo = (CFoo*)p;
That is, static_cast is basically the same as an ordinary cast. But not exactly, because you can’t use static_cast to cast away const-ness or volatility. To cast away const-ness, you must use const_cast.
 const CFoo* pcfoo;
 pFoo* pFoo = const_cast<CFoo*>pcfoo;
 pFoo->x = 10 // now you can modify
Some of you may be wondering: what’s the big fuss about static_cast? Not much. It’s mainly a way to write more human-readable code. By using static_cast, you state to the entire world, “I am making a cast here, in case you hadn’t noticed!”—something you may or may not be proud of. Likewise, const_cast makes it clear you’re casting away const-ness, so you don’t have to type a comment like “use cast to remove const-ness.” Also, static_cast and const_cast are easier for compilers to parse, instead of the old parentheses syntax, which could be confused for an expression. Some day (in a hundred years or so), the old-style cast could be expunged.
While static_cast may seem a little brain damaged, dynamic_cast is more useful. It lets you safely perform a cast down or across an inheritance hierarchy.
 class X { ... };
 class D : public X { ... };
 void func(X* px)
 {
     D* pd = dynamic_cast<D*>px;
     if (pd) {
         // cast succeeded
     } else {
         // cast failed
     }
 }

Here, dynamic_cast<D*> returns a pointer to D object if px really points to an object of class D. It returns NULL otherwise. You can use dynamic_cast to cast references as well as pointers. C++ compiler developers are free to implement dynamic_cast as they want, but you usually have to use a special option to turn on the RTTI (Run-Time Type Information) features (see Figure 3).

Figure 3  Enabling RTTI
Figure 3  Enabling RTTI


Finally, a word of advice from Uncle Paul. STATIC_ DOWNCAST and static_cast are good; DYNAMIC_DOWNCAST and dynamic_cast are bad. This is an oversimplification, of course, but STATIC_DOWNCAST adds extra bulletproofing, and STATIC_DOWNCAST and static_cast both make casts stand out. The dynamic versions, on the other hand, encourage you to write bad code by relying on type checks you shouldn’t have to make. Whenever you find yourself doing type checks in C++, it’s likely that your design is flawed. The whole point of virtual functions and polymorphism is to avoid that sort of thing. You almost never need it.

Leave a Reply

Your email address will not be published. Required fields are marked *