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 > March 1999
March 1999

Microsoft Systems Journal Homepage

C++ Q&A

Code for this article: Mar99CQA.exe (2KB)
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 a program that starts a thread. The thread uses PostMessage to post a private message back to the main thread. The program works perfectly in debug mode, but it crashes in the release build. I searched the newsgroups for quite a long time and found a couple of posts with a similar problem, but none with any solution. I appreciate any help you can offer.
Stanley Siu

A There must be a strange misalignment in the spheres because all of a sudden several readers have asked me this question, and I recently bumped into the same problem as well. Normally when there's a works-in-debug, fails-in-release problem, the first thing to look for is some code you accidentally put in an ASSERT statement, such as:

 ASSERT((x=DoSomething()) != 5); 
Here, the assignment x=DoSomething is omitted in release builds since ASSERT evaluates to a no-op. The way to fix it is to use VERIFY.

 VERIFY((x=DoSomething()) != 5);
VERIFY is like ASSERT; it triggers a debug break if the expression evaluates to zero. But unlike ASSERT, VERIFY retains the expression even in release builds.
When you've checked your code thoroughly and you can't find any faulty ASSERTs, the next thing to look for is an uninitialized data problem, though usually MFC finds this sort of bug with its debug initialization tricks (see my November 1998 column). If you can't find any bad ASSERTs or uninitialized objects, the next thing to do is whimper.
Your problem is particularly sticky because the crash happens far away from the faulty code. That's often a clue that you've munged your stack in some gruesome way. Indeed, that turns out to be the case here. The bug has nothing to do with ASSERT, data initialization, PostMessage, or even multithreading. It has to do with the way you declare your message handler.
Normally, when you write some code to post (or send) your own private message, you define a message ID and add an ON_MESSAGE handler in your message map.

 // in message map 
     ON_MESSAGE(WM_FOO, OnFoo)
The official signature (function prototype) for an ON_MESSAGE handler requires a WPARAM and an LPARAM, and returns an LRESULT. In other words, you must declare your handler function like so:

 class CMyWnd {
 •
 •
 •
     afx_msg LRESULT OnFoo(WPARAM wp, LPARAM lp);
 };
This differs from the command handlers used in ON_COMMAND, which have a signature that's all void.

 // command handler has no args 
 afx_msg void OnSomeCommand();
However, since most programmers are human, it's easy to make the mental slip of using the ON_COMMAND signature with an ON_MESSAGE handler, particularly if your handler doesn't use WPARAM, LPARAM, or the return code. So instead of declaring your function the way it should be for ON_MESSAGE, you accidentally declare it à la ON_COMMAND, a function with no arguments and no return value. You might expect the compiler to complain—but noooo. Why not? Because ON_MESSAGE is an MFC macro that's used to generate a message map entry by casting your function to the appropriate type.

 // from afxmsg_.h 
 #define ON_MESSAGE(message, mbrFn) \
     {message, 0, 0, 0, AfxSig_lwl, \
     (AFX_PMSG)(AFX_PMSGW)(LRESULT \
     (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&mbrFn },
The important thing to note here is that ON_MESSAGE casts mbrFn to a CWnd member function that takes a WPARAM and an LPARAM and returns an LRESULT. It casts to AFX_PMSGW, and then to AFX_PMSG. AFX_ PMSG is defined as a CCmdTarget function with no args that returns void; AFX_PMSGW is the same thing for a CWnd. None of this matters, however; the point is that ON_MESSAGE casts your function to the type it needs, so whatever signature you use, the compiler processes it with nary a peep. In the case of built-in message handlers like ON_WM_CREATE, ON_WM_SETFOCUS, and so on, the function name is built into the macro, so there's less chance of flubbing it; with ON_COMMAND and ON_MESSAGE you can give your handler function whatever name you like, but you're on scout's honor to use the proper arguments and return type. If you don't, that code-wrangler merit badge won't be any help.
To understand why, you have to delve into assembly language. Yuk, you say? Don't worry, this will be quick. Let's say you have a correct OnFoo handler with WPARAM and LPARAM:

 LRESULT CMyWnd::OnFoo(WPARAM wp, LPARAM lp) 
 {
    return 0; 
 }
Visual C++® 5.0 generates this code for the function:

 ; {
     push ebp
     mov ebp, esp
     push ecx
     mov DWORD PTR _this$[ebp], ecx 
 ; return 0
     xor eax, eax 
 ; }
     mov esp, ebp
     pop ebp
     ret 8
The important thing is the ret 8 at the end. That tells the processor to return to the next instruction on the call stack (EIP register) and, by the way, increment the stack pointer (ESP) by eight, please. That's to wipe the eight bytes, WPARAM and LPARAM. If you declare your function with no arguments, the compiler generates ret 0 instead of ret 8, which means no bytes are removed and your stack has been corrupted. The caller pushed two arguments, but the epilog failed to remove them. You might wonder why the callee is undoing something the caller did when that seems to violate one of the cardinal rules of programming: he who does should also undo (that is, the do and undo should both happen in the same place)—but that would lead me to a discussion of calling conventions, in which case you'll need to ingest some NoDoz tablets.
If the stack is corrupted, why does it work in debug mode? Good question. The honest answer is, you got lucky. A program with a bad stack can often go on blithely executing without any unhappy symptoms. Indeed, a close friend of mine who writes the Bugslayer column (whose name will go unmentioned) assures me that some quite famous commercial applications do this. A bad stack is like a time bomb. It doesn't actually go off until someone tries to access a bad argument somewhere. But one reason this may be less likely in a debug than a release build is the different prolog/epilog used.
As you can see from the following instructions, the standard debug prolog saves the stack pointer first thing

 push  ebp 
 mov ebp, esp
and the epilog restores it:

 mov esp, ebp 
 pop ebp
This adds a bit of robustness; if any of the functions called within OnFoo messes up the stack pointer, the error will be corrected before OnFoo returns. Of course, OnFoo will then mess everything up if it does ret 0 instead of ret 8. But if the function calling OnFoo has the same ESP-correcting prolog/epilog, it may fix the stack before it can release any bad karma into your app. In release builds, however, the ESP-correcting prolog/epilog is typically optimized out of existence. This explains why a stack botch-up is more likely to result in negativities in a release build.
So what's the moral of the story? Even in these glory days of type checking and programmer-friendly compilers, a good programmer can always find a way to circumvent the system and shoot himself in the foot.

Q I just had a discussion with some other developers, and we have different opinions about using the static keyword, both for attributes and member functions in object-oriented programs. One group says the static keyword should be avoided because it's contradictory to the idea of OOP. Polymorphism is unavailable for static members, and encapsulation is not really guaranteed. The others say the static keyword is part of OOP and should be used—for singleton objects, for example. What's your opinion?

Identity withheld
OOP Witness Protection Program

A Oh boy, an opinion question! I just can't resist. I love these theoretical OOP questions. Debating whether something is object-oriented is like debating how many angels fit on the head of a pin. In other words, it's a useless question. The goal is not to follow some abstract paradigm, but to write programs that work—programs that are reliable, robust, and easy to comprehend, change, and maintain.
Object-oriented is only useful insofar as it assists in reaching this goal. If you were to judge software by the degree to which the design adheres to some internal model of perfection, Windows
® would surely get the lowest possible score (somewhere below 1 on a scale of 0 to 10). And yet in what system is everyone programming? Even COM isn't strictly object-oriented, but it's the best method so far for implementing binary-reusable software components. (CORBA fans would disagree—so OK, COM is one of the best.)
If you say static members are not polymorphic, well then the same is true for non-virtual functions. Should they be banned? Purists say yes; in a truly object-oriented system all functions are virtual. In the Java language, functions are virtual by default. If static functions don't provide true encapsulation, then neither do public and protected data members. In fact, the whole design of C++ objects flies in the face of encapsulation since everything depends on the layout of objects. If you add or subtract even a single data member—public, protected, or private—you have to recompile the entire system. What kind of encapsulation is that? If you want true encapsulation, you need COM, where there's no data, only interfaces.
So as with all meaty ideas, you can debate endlessly what OOP means. As a simple programmer trying to get something done (and usually under deadline), I leave it to ivory towerists who get paid for such activities to decide how many objects fit on the head of a pixel. For me, whether or not static class members are object-oriented is simply uninteresting. The only question is, are they useful? The answer is definitely yes.
Static members are great for any data or function that there's naturally just one of for the entire class—in other words, globals. The most obvious example of a class global is the class's virtual function table. MFC provides other examples; message maps, COM interface maps, dispatch maps, event maps, and all the other kinds of maps MFC uses are static class members. The CRuntimeClass object that identifies each class to MFC is also a static class member for each class. Many of these objects are hidden within familiar macros such as DECLARE_DYNAMIC or DECLARE_MESSAGE_MAP. All the MFC CSomething::FromHandle functions are static because they obtain an instance of an object from thin air—that is, without an object pointer to begin with. The temporary and permanent handle maps are likewise static class objects.
I often use static members for variables that control the behavior of the entire class. For example, I typically use a flag CFoo::bTrace that lets you turn on TRACEing for the CFoo class. I predicate all my TRACE diagnostics on if (bTRACE). In my cool UI enhancements (CCoolMenuManager, CCoolBar, and so on) from past columns, I use a class global to hold the version of ComCtl32.dll that resides on the system. And any time you want to implement a callback function in a class such as a window proc or an enumerator function with a normal C signature (no hidden this parameter), you must declare it as static. Often these callback functions require C or Pascal linkage.
I answered this question mainly so that you will know my bias, which only seems fair. The way I approach programming is: here are all the tools in my bag of tricks. Now, what's the most useful tool to get something done in a particular situation? I love OOP. It's a great paradigm. It's warm and fuzzy, way cool, and full of goodness. But as the economist Joseph Schumpeter once said, "Insofar as the system is perfect, it doesn't work; insofar as it works, it isn't perfect." Or something like that.

Q I'm writing a COM object using MFC. I've declared my class with DECLARE_OLECREATE and implemented it using IMPLEMENT_OLECREATE. I also use the DECLARE_INTERFACE_PART macros to build interface maps in the standard MFC way. When I register my object using REGSVR32.EXE, MFC performs a lot of magic to add my COM object to the system registry, but I want to add my own registry entries such as the categories my object supports. The COleObjectFactory::Register function looks like it does what I want, if I could override it. But I can't figure out how to get MFC to use my own class factory. Help!

John Padnick

A Well, you're on the right track. COleObjectFactory:: Register is indeed the function that adds all the registry stuff. MFC's hardwired implementation works for standard controls, but if you want to do something else, you have to override it, which is why COleObjectFactory:: Register is virtual. You can derive a new class and override Register, but as you've discovered, the $64,000 question is: how do you get MFC to use it?
The answer lies in the macros you mention in your question: DECLARE_ OLECREATE and IMPLEMENT_ OLECREATE. These are the macros that declare and implement the class factory for an MFC COM object. DECLARE_OLECREATE declares two static class members (readers of the previous question take note):

 static COleObjectFactory factory; 
 static const GUID guid; 
The first is the class factory, and the second is the GUID for your COM class. IMPLEMENT_OLECREATE takes a class name (such as CMyComObj), an external name (My COM Class, for example), and a bunch of hex numbers that specify the guid. A typical IMPLEMENT_OLECREATE statement as generated by the GUIDGEN program (see Figure 1) looks like this:

 // {AE549340-98D5-11d2-A0D0-004033D0645D} 
 IMPLEMENT_OLECREATE(CMyComObj, "My COM class",
     0xae549340, 0x98d5, 0x11d2, 0xa0, 0xd0,
     0x0, 0x40, 0x33, 0xd0, 0x64, 0x5d);
I've filled in the class name and external name, which guidgen leaves out.
Figure 1 Generating a GUID
Figure 1 Generating a GUID

The preprocessor expands IMPLEMENT_OLECREATE to the following lines of code:

 COleObjectFactory CMyComObj::factory(CMyComObj::guid,
     RUNTIME_CLASS(CMyComObj),
     FALSE, _T("Generic COM Object"));
 
 const GUID CMyComObj::guid = { 0xae549340, 0x98d5, 
	    0x11d2, { 0xa0, 0xd0, 0x0, 0x40, 0x33, 0xd0, 
    0x64, 0x5d } };
DECLARE_OLECREATE and IMPLEMENT_OLECREATE always give you a class factory and a GUID with the names "factory" and "guid", and the factory is always of type COleObjectFactory. Therein lies the rub. The name COleObjectFactory is hardwired into the macro; there's no way to specify your own class name instead.
Not to worry. Just because MFC gives you macros doesn't mean you have to use them! All you need is a guid and a class factory. How you get them is up to you. There's no reason you can't skip the MFC schtick and just write the code yourself.

 // in header file 
 class CMyComObj : public CCmdTarget {
     static CMyFactory factory; // note type!
     static const GUID guid;
 .
 .
 .
 }
 
 // in .cpp file
 CMyFactory CMyComObj::factory( ... ); 
 const GUID CMyComObj::guid = { ... };
Now all you have to do is implement CMyFactory and override the Register function to your heart's content.
I've shown you this way of doing things so you'll realize it's possible and that there's nothing mystical or mandatory about all these MFC macros you see floating all over the place. However, there is another way to create your own custom class factory. MFC provides yet another set of macros: BEGIN_OLEFACTORY, END_OLEFACTORY, and IMPLEMENT_OLECREATE_EX.
Instead of generating a class factory using the hardwired class name COleObjectFactory, these macros generate a nested class with a name based on the name of your control class. If the name of your control class is CFooCtrl, the name of the nested factory class is CFooCtrl::CFooCtrlFactory. The MFC ActiveX
® Control Wizard uses BEGIN_ OLEFACTORY and END_OLEFACTORY to generate a COM object that supports licensing (see Figure 2). The way it works is that you code BEGIN_OLEFACTORY, followed by END_OLEFACTORY, and in between you put any functions you want to override or add to your factory class. You can even add data members—anything you could put in a C++ class declaration.

 class CFooCtrl : public COleControl {
     BEGIN_OLEFACTORY(CFooCtrl) 
     private: 
         // categories supported 
         CATID        m_catid[2] 
     public: 
         // override to register categories 
         virtual BOOL Register();
     END_OLEFACTORY(CFooCtrl) 
 };
In Figure 2, MFC overrides the functions required to support licensing. To understand how it works, all you have to do is take a look at the code generated by the preprocessor. BEGIN_OLEFACTORY(CFooCtrl) generates a nested declaration like so:

 // (within class declaration) 
 class CFooCtrlFactory : public COleObjectFactoryEx { 
 public:
     CFooCtrlFactory(/* lot's o' args */) {} 
     virtual BOOL UpdateRegistry(BOOL);
By default, you get an UpdateRegistry function; the ActiveX Control Wizard generates one for you that registers your COM control. Note that BEGIN_OLEFACTORY does not generate a closing curly brace, so any lines of code that follow belong to the nested class declaration for CFooCtrlFactory. (If you weren't aware that you can declare a class within a class, now you know that it's just another one of the amazing, confusing features of C++.)
END_OLEFACTORY closes the declaration with a curly bracket and adds some more stuff of its own.

 }; // end class declaration 
 friend class CFooCtrlFactory;  
 static CFooCtrlFactory factory;  
 public:
 static_DATA const GUID guid;  
 virtual HRESULT GetClassID(LPCLSID pclsid);
END_OLEFACTORY makes the factory class a friend of the main (control) class, declares a static instance of CFooCtrlFactory and a guid (just like DECLARE_OLECREATE), and adds a new function, GetClassID.
BEGIN_OLEFACTORY and END_OLEFACTORY only declare things; everything is implemented in IMPLEMENT_ OLECREATE_EX, which expands more or less as follows:

 CFooCtrl::CFooCtrlFactory CFooCtrl::factory(...); 
 const GUID CFooCtrl::guid = {...}; 
 HRESULT CFooCtrl::GetClassID(LPCLSID pclsid)  
     { *pclsid = guid; return NOERROR; }
This looks just like IMPLEMENT_OLECREATE with a class name change and the addition of GetClassID (which you or MFC can use to implement the COM interface IPersist). If you use BEGIN_OLEFACTORY, you also have to implement CFooCtrl::UpdateRegistry. The ActiveX Control Wizard will generate one for you (see comctl.cpp in Figure 2). The ActiveX Control Wizard only uses BEGIN_ OLECREATE and END_OLECREATE if you request a control that supports licensing; for a vanilla ActiveX control, the wizard generates yet another macro, DECLARE_ OLECREATE_EX. Fortunately, this one is just shorthand for the following:

 BEGIN_OLEFACTORY(class_name) 
 END_OLEFACTORY(class_name)
This has the effect of generating a nested class with only one function override: UpdateRegistry. Remember, if you use the macros yourself (not generated by the wizard), you must write UpdateRegistry yourself. And you have to remember that whatever functions you decide to override (such as Register), you must use the doubly scoped nested notation:

 BOOL CFooCtrl::CFooCtrlFactory::Register()
 {
     // do your funky thing here 
 }
Hey, no one ever said COM was easy!


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

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

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

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