Use elementsof(sz), not sizeof(sz)
I had to fix a bug recently where my shell extension was crashing another application when you used that app’s File Open dialog.
This application has a thumbnail view of the selected file in the File Open dialog, which they generate the same way as Windows Explorer: by loading a shell extension for the selected filetype and calling its IExtractImage
interface. It’s a fairly weird protocol: First they call your IPersistFile::Load
to give you the filename, then you give them back the same filename when they call IExtractImage::GetLocation
. Finally they call IExtractImage::Extract
and that’s when you generate the thumbnail.
But, after my GetLocation
method returned, the application silently exited. What could be wrong? My code worked fine in Explorer.
GetLocation
is a typical function that takes a character string buffer and length along with some other parameters (omitted here):
I noticed that this other app was giving me an unusually large file pathname buffer, 520 characters or 1040 bytes to be exact. This number sounded strangely familiar (and not just because of this).
Then I realized what happened. I’ve never seen the source code for this app I was crashing, but I just know it looked like this:
Oops. The cchMax
argument to GetLocation
is a length in characters, but sizeof
gives you the size in bytes. And we’re talking WCHAR
here, so each character is two bytes. MAX_PATH
is 260, making szPath
520 bytes long, the number that they passed into my code.
One way to fix the problem is:
That gives correct code, but I never like seeing MAX_PATH
repeated like this. sizeof
is in the right spirit, actually measuring the array length instead of repeating a constant, but it measures the wrong thing, bytes instead of characters (array elements).
I like to code this with the elementsof
macro, defined as:
Then you can just use elementsof
instead of sizeof
:
elementsof
is handy anytime you need the length of a character string array or any array.
Of course, I didn’t have the luxury of fixing this code at its source (other than reporting the bug to the program’s authors). So I worked around it by checking for the bogus 520 character cchMax
and cutting it back to 260 (MAX_PATH
) characters.
Small typo in the last code block: elementsof(pszPath) should be elementsof(szPath).
Thanks for the sharp eye, Stephanie. That’s what I get for posting in the wee hours! Fixed now.
I like to use:
That way it protects against doing a lengthof on a pointer instead of an array. Doesn’t work for local types though because of the way C++ templates work but you run into those rarely and easy to work around.