Click Here to Install Silverlight*
United StatesChange|All Microsoft Sites
MSDN
|Developer Centers|Library|Downloads|Code Center|Subscriptions|MSDN Worldwide
Search for


Advanced Search
MSDN Home > MSJ > November 1998
November 1998

Microsoft Systems Journal Homepage

C++ Q&A

Paul DiLascia is the author of Windows ++: Writing Reusable Code in C++ (Addison-Wesley, 1992) and a freelance consultant and writer-at-large. He can be reached at askpd@pobox.com or http://pobox.com/~askpd.

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.

Q I have a class called CMyComboBox that's derived from the MFC class CComboBox. I also have a dialog class with a CMyComboBox member that maps a combobox control to an instance of CMyComboBox. My combo class has a handler function for the reflected CBN_SELCHANGE notification message. Since the combobox handles the notification using message reflection, the dialog never gets a chance to handle CBN_SELCHANGE. How can I implement CMyComboBox in an object-oriented manner so it handles the CBN_SELCHANGE notification, but still let the dialog handle the notification as well?

Vasile Paraschiv

A Use ON_NOTIFY_REFLECT_EX instead of ON_NOTIFY_REFLECT, and return TRUE from your handler.
 BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)
     ON_NOTIFY_REFLECT_EX(CBN_SELCHANGE, OnSelChange)
 •
 •
 •
 END_MESSAGE_MAP()
 
 BOOL CMyComboBox::OnSelChange(...)
 {
 
     // do your thing
 •
 •
 •
     return TRUE; // keep routing
 }
All the message-handling macros—like ON_COMMAND, ON_NOTIFY, ON_RANGE, and so on—have XXX_EX versions that add the ability to continue processing the message or notification. Instead of void, the handler function returns a Boolean value: TRUE tells MFC to keep routing the message and FALSE means don't route the message. The XXX_EX versions are useful in situations where you want to let more than one command target handle a message. In this case, you want the combobox and dialog both to be able to handle CBN_SELCHANGE.
This is a good question, because I would argue that when you use message reflection to implement a self-contained control, you should almost always use the XXX_EX form and return TRUE. There's no reason in principle to block the parent window from seeing the notifications. They tell the parent window, "Hey, something interesting just happened to me." For example, the user changed the selection in your combobox. Such notifications should be public.
A programmer using your special combo widget might want to extend it with some new feature you never thought of, like displaying the current item in the dialog's title bar. Needless to say, this is difficult if your combo class gobbles the relevant notifications. Your programmer/client is likely to curse and mumble, then sneak around your too-restrictive code by overriding CWnd::WndProc or some other function low in the message-processing food chain. If you use ON_NOTIFY_REFLECT_EX and return TRUE, other programmers using your code will instead smile and think, "Whoever wrote this class is pretty sharp."

Q I have a dialog with a listbox I want to update when the user presses a button. My Update button causes the listbox to completely recalculate itself, deleting all the items and then adding them again. The code works fine, but the display looks a little slow and choppy when all the items are redrawn. Is there some way to make the items draw faster, or at least not draw anything until I've calculated the new list items? I'm using MFC version 5.0.

Lisa Bergen

A Funny you should ask. In fact, there's a function designed for just this purpose: CWnd::SetRedraw. This function takes a Boolean argument that tells a window (in this case your listbox) whether to draw as you add or delete items. The standard way to recalculate all the items in a listbox is like so:
 void CMyListBox::RecomputeItems()
 {
     SetRedraw(FALSE);     // turn drawing off
     ResetContent();       // delete all items
     for (/* loop */) {
         AddString("foo"); // or other add function
     }
     SetRedraw(TRUE);      // turn drawing back on
     Invalidate();         // to guarantee repaint
     UpdateWindow();       // repaint now (optional)
 }
Now the listbox won't paint anything as you add and delete items, only at the end when you call Invalidate/UpdateWindow. SetRedraw is an MFC wrapper function that sends a WM_SETREDRAW message to your listbox. WM_SETREDRAW is a general-purpose message you can send to any window, but the only built-in windows that do anything with it are listboxes and comboboxes. (Some of the newer controls may also handle WM_SETREDRAW, so don't quote me on that.)
If you're writing your own fancy control, you may want to handle WM_SETREDRAW so programmers can use it the same way as with list and comboboxes. But in truth, WM_ SETREDRAW is a kludge because the functions that add items to a list or combobox shouldn't be doing any repainting in the first place; they should only invalidate the window, which would cause it to be repainted eventually, but not right away. It's only because list and comboboxes paint the newly added items immediately that SetRedraw is necessary. If you implement painting cleanly—which means that the only function that actually modifies bits on the screen is your WM_PAINT/OnPaint handler, or OnDraw for a view—then there's no need for redraw flags.
In general, operations that modify your control's appearance should only invalidate the area modified and let OnPaint do the actual drawing when Windows gets around to sending a WM_PAINT message. If some other part of your system needs to update immediately, it can always call UpdateWindow, which forces a WM_PAINT message if there's anything to paint (that is, any invalid regions). This way, someone using your control can call a sequence of methods, such as multiple calls to AddString (in the case of a listbox), without having the screen flicker as it paints the screen on every operation.
There are special situations where you may think you need to paint something right away to make a particular screen update fast, but I'd avoid this like the plague. The whole purpose of Invalidate/OnPaint is to let you queue regions for painting in one fell swoop, thus avoiding one source of flicker and deferring painting, which could be slow, until the user isn't doing anything. In text editors, fast typists can often get ahead of the computer. If a fast typist types ten characters, it might be too slow to display each one, and better to display all ten when the user pauses a moment. (Admittedly, this particular example is less relevant in the age of 333MHz Pentiums, but it all depends on how slow your editor is!)
Moreover, if you religiously restrict all painting to OnPaint, it's much easier for another programmer using your control to change the way painting works. If you've ever tried to do custom painting for an edit control, you know what I mean. There's a half dozen or so places where the edit control draws, including when a character is typed, when a character is deleted, and when text is selected. It sometimes takes a little extra work to do painting correctly, but the extra effort is well worth it in terms of clean design and avoiding the paint jitters. Otherwise, you may have to resort to WM_SETREDRAW.

Have a question about programming in C or C++? Send it to askpd@pobox.com

From the November 1998 issue of Microsoft Systems Journal. Get it at your local newsstand, or better yet, subscribe.

© 1998 Microsoft Corporation. All rights reserved.
Terms of Use
.

© 2016 Microsoft Corporation. All rights reserved. Contact Us |Terms of Use |Trademarks |Privacy & Cookies
Microsoft