Re: AfxRegisterWndClass() within dll

Tech-Archive recommends: Fix windows errors by optimizing your registry



On Sun, 31 Aug 2008 05:33:00 -0700, tfs <tfs@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:



"Joseph M. Newcomer" wrote:


BOOL CMsgOnlyWnd::Create()
{
static LPCTSTR sg_lpszWndClass = ::AfxRegisterWndClass(0);


****
Take as a fundamental programming rule: writing a static declaration like this a mistake.
In the few, incredibly rare (once every five years or so) situations in which it could
possibly make sense, you will recognize them. But just assume that this technique ranks
among the poorest possible programming practices in any environment, including non-Windows
C code. Go from there. (Just because something is syntactically possible doesn't mean it
makes sense from a programming viewpoint)
joe
****

Honestly, I hardly agree with you about your viewpoint (of using static
declaration in the way my example illustrated). As I am not an expert on
MFC/Win programming, I don't argue with you on that when involving any
Windows entity. But you also slam on the non-Windows C-code? This technique
is listed in Marshall Cline's C++ FAQ to resolve 2 global instances (defined
in different .c/.cpp files) referencing each other. And I have used this
technique, and conventional static global variables in my many singleton
classes, to resolve numerous cross-dll design issues that otherwise will be
far too complex to deal with, and they are not some
hack-and-hope-it-does-not-break codes, all created-when-needed, clean-exit
and no resource leak.
***
Feel free to disagree. But you have absolutely demonstrated why it cannot work correctly
in this context, and there are many, many more contexts in which it will fail.

And yes, it was a bad idea in C code as well. I learned this over many, many years of
finding (and sometimes creating) bugs because of using it, and gradually came to the
conclusion that there is no sane condition in which a non-const local static makes sense.
It interferes with both windowing and threading. The presence of such declarations are
simply land mines waiting for the innocent programmer to step on them.

Note that just because something is syntactically possible does not mean it makes sense.
No matter how many FAQs use it (since you didn't give a URL, I didn't bother to look it
up). But "to resolve 2 global instances" immediately makes me question why there are two
global instances of anything; it suggests that this is a way of solving a problem that
should not have been allowed to exist in the first place.

Singleton classes are a different case; they do not use static local variables.

And for DLL solutions, you have to ask "is this DLL thread-safe" and worry about what
happens if functions in the DLL are called from separate threads; that's where
locally-scoped static variables really break code. They also break code badly when you
have to avoid "resource leaks" that are not "storage leaks", which is the exact case you
have. Had you not immediately thought of using a locally-scoped static variable, you
would not have created a solution that cannot ever possibly be made to work correctly
under any conditions. It gives the brief illusion of working, but it is only an illusion.
As you discovered. It doesn't work. It doesn't work because you are not able to
unregister the class because the onlly reference to the class is hidden and cannot be
found.

Statically-allocated storage must be handled very carefully in windowing context and
multithreading contexts, and in DLL contexts where the DLLs can be loaded dynamically. If
you develop bad programming habits, as soon as you extend these habits into contexts where
they cannot work, you get screwed. So the best solution is to not develop the habits at
all, that way, you don't casually do something that cannot work, but breaks in subtle ways
only under unusual conditions.
****

And besides, a local CONSTANT static declaration is to reduce global
namespace pollution and enhance data encapsulation. It is indeed an old
technique, but it will still make sense now and in the years to come. If you
are trying to talk about multi-thread issue, then I may answer: do I have to
get every single classe and function multi-thread ready?
****
Remember, I said the only valid use was when the declaration was preceded by 'const'?

It is not a bad idea to program all your classes as if they will be multithreaded; that
way, when you do add threading, you don't have everything implode, and you don't have to
go looking for hard-to-find bugs that are timing-sensitive. They aren't there.

I've watched people make these same mistakes, over and over, for decades. So I try to
avoid creating situations in which these mistakes are fatal. I'm usually the guy called
into "fix our multithreading problems" and this is one of the most common failure modes.
1975 coding techniques do not work well in multithreaded code (oh yes, if you say, "I
don't use threads", be aware that windowing looks an awful lot like multithreading with
cooperative rather than preemptive allocation of the time)
joe
****

tfs

Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.



Relevant Pages

  • Re: MFC dll and exe porting to 64-bit
    ... Why the obsolete 'char *' instead of the proper LPTSTR? ... We are no longer programming 16-bit windows in an 8-bit character world, ... string arguments should probably be LPCTSTR, that is, const parameters. ... declaration of the function itself, in context (meaning show the surrounding class ...
    (microsoft.public.vc.mfc)
  • Re: How to convert Infix notation to postfix notation
    ... is a definition, the one without a function body is a declaration, also ... You also don't understand the intent or purpose of the feature. ... Prototypes are primarily used to address the fairly common case where the ... You need to actually learn a radically different programming language. ...
    (comp.lang.c)
  • Re: Graphing problem
    ... programming methodology" is not an exaggeration? ... All other poor styles of doing Windows programming methodology emulate Petzold. ... No declaration of this variable is shown. ... The scope and lifetime of a variable should be as narrow as possible. ...
    (microsoft.public.win32.programmer.gdi)
  • Re: Is C99 the final C? (some suggestions)
    ... The C standard specifies what is UB and what's not. ... If you have multithreading, they you have to lock and unlock ... > your heap, or use other strategies to make sure one thread isn't in the middle ... Having a different set of condoned operators at each programming ...
    (comp.lang.c)
  • Re: advice on programming style: is multiple inheritance bad?
    ... contexts, such as accounting, image processing, or networking. ... Humans don't work in single contexts. ... Object-oriented programming is not meant to replicate natural language. ... think of inheritance is a "has functionality of" relationships." ...
    (comp.lang.python)