Holy cow, I wrote a book!
I'm sure it's been drilled into your head by now that
you have to free memory with the same allocator that
LocalAlloc matches LocalFree,
GlobalAlloc matches GlobalFree,
new matches delete.
But this rule goes deeper.
If you have a function that allocates and returns some data,
the caller must know how to free that memory.
You have a variety of ways of accomplishing this.
One is to state explicitly how the memory should be freed.
the FormatMessage documentation
explicitly states that you should use the
LocalFree function to free the buffer that is
allocated if you pass the FORMAT_MESSAGE_ALLOCATE_BUFFER flag.
All BSTRs must be freed with SysFreeString.
And all memory returned across COM interface boundaries must be
allocated and freed with the COM task allocator.
Note, however, that if you decide that a block of memory should
be freed with the C runtime, such as with
or with the C++ runtime via
delete or delete,
you have a new problem: Which runtime?
If you choose to link with the static runtime library,
then your module has its own private copy of the C/C++ runtime.
When your module calls new or malloc,
the memory can only be freed by your module calling
delete or free.
If another module calls delete or free,
that will use the C/C++ runtime of that other module
which is not the same as yours.
Indeed, even if you choose to link with the DLL version of the
C/C++ runtime library,
you still have to agree which version of the C/C++ runtime to use.
If your DLL uses MSVCRT20.DLL to allocate memory,
then anybody who wants to free that memory must also
If you're paying close attention, you might spot a looming problem.
Requiring all your clients to use a particular version of the C/C++
runtime might seem reasonable if you control all of the clients
and are willing to recompile all of them each time the compiler changes.
But in real life, people often don't want to take that risk.
"If it ain't broke, don't fix it."
Switching to a new compiler risks exposing
a subtle bug, say, forgetting to declare a variable
as volatile or inadvertently relying on temporaries having a particular
In practice, you may wish to convert only part of your program
to a new compiler while leaving old modules alone.
(For example, you may want to take advantage of new language
features such as templates, which are available only in the new
But if you do that, then you lose the ability to free memory
that was allocated by the old DLL, since that DLL expects you to
whereas the new compiler uses MSVCR71.DLL.
The solution to this requires planning ahead.
One option is to use a fixed external allocator such as
LocalAlloc or CoTaskMemAlloc.
These are allocators that are universally available
and don't depend on which version of the compiler you're using.
Another option is to wrap your preferred allocator inside
exported functions that manage the allocation.
This is the mechanism used by the NetApi family
For example, the NetGroupEnum function allocates
memory and returns it through the bufptr parameter.
When the caller is finished with the memory, it frees it with the
In this manner, the memory allocation method is isolated from the caller.
Internally, the NetApi functions might be using
LocalAlloc or HeapAllocate or
possibly even new and free.
It doesn't matter; as long as NetApiBufferFree frees
the memory with the same allocator that
NetGroupEnum used to allocate the memory in the first place.
Although I personally prefer using a fixed external allocator,
many people find it more convenient to use the wrapper technique.
That way, they can use their favorite allocator throughout their
Either way works.
The point is that when memory leaves your DLL, the code you gave
the memory to must know how to free it, even if it's using a different
compiler from the one that was used to build your DLL.
There'll be the big announcement promising a revolution
in the computer industry,
lots of press coverage,
and then... nothing.
What ever happened to these companies and products?
Does anybody know?
Take care not to hard-code boldfacing or italics into your code.
Chinese and Japanese characters (and to a somewhat
lesser extent, Korean characters)
do not suffer many types of boldface well.
(The three scripts Chinese, Japanese and Korean are collectively
called "CJK" scripts.)
Many characters are very intricate, and making the strokes bolder
can result in a big blob of ink.
Consider the Traditional Chinese character
慶 which means "celebrate".
Making it boldface results in
慶 which, depending on which operating system and fonts you
have installed, might come out as an unreadable mess.
Similarly, CJK scripts do not often use italics on screen,
since they also make the characters harder to read.
What should you do in your program if you need to emphasize something?
You should let the localizers choose how they want the emphasis to
be performed by allowing them to specify the font face, size and
That way, the localizers for Western languages can specify boldface,
whereas those localizing for Chinese or Japanese can specify
a larger font size or different font face instead.
Different versions of Windows cope with boldface CJK fonts with
different degrees of success.
Windows 2000, as I recall, used a simplified simulated boldface,
which didn't handle CJK fonts very well.
Windows XP, I'm told, has an enhanced boldface simulation algorithm
for CJK fonts.
The result is not perfect, but it is much better than what was available
in Windows 2000.
Windows Vista finally bridges the gap and provides separate boldface
fonts for CJK.
These custom boldface fonts have been tuned specifically for this purpose
and (I'm told) are quite readable.
It really all started with
The music for that game is so darned infectious, and it was
my fascination with that music that prompted my colleague to
loan me the CDs his wife bought while she traveled through Asia.
I already mentioned
China Dolls (中國娃娃).
Another of the CDs in the collection was
4th Let's Go!),
the um fourth album from the J-Pop group
I'm sure somebody will correct my Japanese translation.
Yes, these are the girls who in the United States are probably known
having pork chops tied to their foreheads while being stalked by
being chased by American fighter Bob Sapp
being freaked out by a clip from the movie The Ring
traumatizing one of its members by dressing her up
like a seal and making her hang out at the polar bear tank.
From what I can gather, they aren't so much a pop music group
as a marketing phenomenon, what with their own television show
and endorsement contracts.
And yes, it's a singing group with thirteen members.
When I first glanced at the album cover, I just assumed that it
was the same four or five singers dressed up in different costumes,
but no, it really is a group with a ridiculous number of members.
Their music is bubble-gum J-Pop, often
but sometimes just plain
really awful or
horrifically I-can't-even-watch-it awful.)
But I found at least the catchy tunes useful,
because they're energetic and kept me going on longer bicycle rides.
It probably helped that I didn't understand the words,
though I strongly suspect
they're singing about love.
(I also find that even the catchy songs tend to be ruined by the videos.)
Setting aside the musical merits,
I have to admire the logistics of organizing a performance of
such a large group.
Compare, for example,
this music video for
Osaka Koi no Uta
= Osaka Love Song)
live performance of same.
In the music video, you can just cut from one vocalist to the next,
but in the live performance, the singers have to physically trade places.
It's so complicated that some dedicated fans have
color-coded the lyrics to keep track of who sings what.
Another of my colleagues more tuned into the contemporary music scene
learned of my fascination with Japanese pop music
and dedicated himself to finding some good Japanese pop music,
just to show me that it's not all bubble-gum.
More on that in the next episode.
When should you mark a method as virtual?
This question has both a technical and a philosophical aspect.
The technical aspect is well-understood:
You mark a method as virtual if you want
calls to the method
to be invoked on the run-time type of the invoked object
rather than on the compile-time type of the invoking reference.
But there is a heavy philosophical aspect to this question as well.
Some people argue that every method should be virtual so that
derived classes can override the behavior of the base class
in ways the base class may not have anticipated.
This grants you maximum flexibility,
avoiding having to redesign the class in the future.
I happen to believe that the cost of this extensibility is
Once you mark a method as virtual,
your life becomes much more complicated.
Every virtual method is an extensibility point,
which means that you have to assume the worst.
You can't hold any locks when calling a virtual method
(else you may deadlock with the derived class).
You have to be prepared for all sorts of reentrancy
because the derived class may have decided to call
MessageBox in its implementation.
You have to revalidate your state after the virtual method returns
because the derived class may have done
"crazy" things inside that virtual method
including possibly destroying the object itself!
(Life gets very interesting when control returns to the
base class with an invalid "this" pointer.)
It takes only a few seconds to type the word
"virtual" but you need to know what you just signed yourself up for.
I'm not saying that virtual methods are bad;
I'm saying that you need to understand what you are doing.
You don't say "Gosh, somebody might want to override this,
so I'll make it virtual."
You have to say, "Gosh, I'm creating an extensibility point
here that needs to be designed and tested."
Of course, if your class is private, then you are the only
person who can derive from the class, and therefore you can
impose rules on what the derived classes are permitted to do
if they override a method, and you have the power to enforce
said rules on those derived classes since you're the one who
wrote them anyway.
But if you allow others to derive from your class,
then you have entered the world of extensibility
and your life has just gotten a lot more complicated.
Although the inflections and compound-mania are largely absent
from the English language, there are still some vestiges
of its Germanic roots.
One detail of English grammar that I often see neglected
is the distinction between the verb+particle and the compound
Consider the verb phrase "to shut down",
which is the one I see misused most often.
This is a verb+particle combination and is treated as two words.
When you turn it into a noun, however,
it becomes "shutdown", one word.
This Knowledge Base article,
for example, manages to keep its head on straight for
most of the article, using the verb+particle for the
verb form and the compound for the noun form:
\\computername: Use this switch to specify the remote computer to shut down.
/a: Use this switch to quit a shutdown operation.
\\computername: Use this switch to specify the remote computer to shut down.
/a: Use this switch to quit a shutdown operation.
But then it slips up towards the end and uses the compound
as a verb:
To schedule the local computer to shutdown and restart at 10:00 P.M. ...
In other Germanic languages the distinction is clearer.
Consider the Swedish and German verbs for "to make up"
(as in, "to make up an alibi"):
In the verb+particle form, the particle comes after the verb,
whereas in the single-word form, the particle comes before the verb.
It's therefore more obvious when you have one word and when you have two.
English does this only rarely,
typically for verbs that retain poetic or archaic appeal
("cast down" → "downcast") and therefore reach back to the
language's German roots for their power.
This is one of the reasons why I'm so
fascinated by the Germanic languages:
The more I learn about the other languages,
the more I learn about my own.
I was talking with someone last year who had a gripe
about a music organizer program.
Suppose you create some playlists and then decide,
"Oh, nevermind, I don't like this playlist."
You highlight the playlist and click "Delete".
You then get a dialog box that asks,
"Do you want to move the songs in this playlist to the Recycle Bin?"
"Well, no, I don't want you to recycle those songs.
I want to keep the songs.
Just delete the playlist,"
you say to yourself and you click "No".
Unfortunately, the program was asking you,
"Do you want to move the songs to the Recycle Bin
or delete the songs permanently from your computer?"
The program had already decided that you wanted to delete the songs
themselves when you deleted the playlist.
It just wanted to know whether you wanted them gone immediately
or just tossed into the Recycle Bin.
Fortunately, my friend had backups of the songs that had mistakenly
been purged from the computer,
but it was still quite shocking to see all the music just plain disappear
when there was no expectation that anything of the sort was going to happen.
When programs put up Yes/No dialogs, they usually don't have a problem
explaining what will happen when you click Yes.
But they also have to make sure users understand what will happen when
they click No.
Window Vista's new
makes it easier for programs
to make it clearer to users what will happen as the result of pushing
a button on a dialog box.
Instead of being limited to just "Yes" and "No", you can put
more meaningful text on the buttons such as "Save" and "Don't Save",
or you could use command buttons and provide an explanatory sentence
for each option.
programs could always have built custom dialogs with these more
but doing so meant designing a dialog box from scratch, positioning
the buttons precisely according to dialog box layout guidelines,
and then writing a custom dialog procedure to handle this new custom
Most people just take the easy way out and use MessageBox.
In Windows Vista there is now a way to build slightly more
complex dialogs without having to design a dialog template.
Be careful, however, not to fall into the same trap with task dialogs.
The original dialog might have been converted to a task dialog with
the buttons "Recycle" and "Don't Recycle", which would not have
solved the problem at all.
It is generally accepted that
language exposure in the first year of a baby's life is important.
To what certainly must be the dismay of couch potatoes everywhere,
researchers at the
University of Washington
determined that it's
particularly important that it come from a live human being.
Watching DVDs doesn't have any effect.
What was particularly notable to the researchers was that
even just five hours of exposure made a significant impact.
Consider this follow-up question to the question from last time:
When I call the PropertySheet function,
can I assume that the
phpage field of the
PROPSHEETHEADER structure will not be modified?
If we take a look at the declaration of the PropertySheet
function, we see that it reads like this:
typedef const PROPSHEETHEADERA *LPCPROPSHEETHEADERA;
typedef const PROPSHEETHEADERW *LPCPROPSHEETHEADERW;
WINCOMMCTRLAPI INT_PTR WINAPI PropertySheetA(LPCPROPSHEETHEADERA);
WINCOMMCTRLAPI INT_PTR WINAPI PropertySheetW(LPCPROPSHEETHEADERW);
Go past all the function declaration specification goo and look
at the parameter list.
It's a const pointer to a PROPSHEETHEADER
structure (either ANSI or Unicode, depending on which flavor of
the PropertySheet function you're calling).
One of the rules for const pointers is that you can read from them
but you cannot write to them.
Consequently, the PropertySheet function is not allowed
to modify the PROPSHEETHEADER structure.
Assuming your code doesn't modify the PROPSHEETHEADER yourself,
any value on exit from the function will be the same
as the value it had on entry.
In the aftermath of the Zidane head-butt incident,
there was a lot of
speculation over what Materazzi might have said to
provoke Zidane's response.
Zidane has said he attacked Materazzi
because he insulted his mother and sister.
Materazzi denied disparaging Zidane's mother.
I immediately noticed the very precise denial from Materazzi.
(I suspect any parent would recognize the same thing.)
my suspicion was vindicated earlier this week:
Italy's Marco Materazzi said he insulted Zinedine Zidane's sister.