|
-
June 21st, 2011, 09:32 PM
#1
The ZeroMemory macro and OPENFILENAME
I noticed that every GetSaveFileName/GetOpenFileName example on the web uses the ZeroMemory macro after initializing the OPENFILENAME structure, like this:
Code:
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(ofn));
My question is why?
Why do I need to fill my structure with zeros?
What is OPENFILENAME any different from any other WinAPI structure I initialized before and didn't use ZeroMemory?
-
June 21st, 2011, 10:10 PM
#2
Re: The ZeroMemory macro and OPENFILENAME
Well, Here is an example in MSDN of using GetSaveFileName without ZeroMemory call.
In your code it is the ZeroMemory that initializes a variable of OPENFILENAME structure with 0-s, and not ZeroMemory called after initialization.
The important thing related to GetSaveFileName/GetOpenFileName is that their parameter, which is the pointer to OPENFILENAME structure is the IN/OUT parameter, which implies that some information within the structure should be passed to the functions .
So typically you initialize the structure members with 0-s, then fill some members of the structure (at least first member of the structure lStructSize should be initialized to sizeof(OPENFILENAME), then call the functions.
-
June 22nd, 2011, 06:28 AM
#3
Re: The ZeroMemory macro and OPENFILENAME
As a rule of thumb, you have to initialize every local, non-static variable, not only structures.
-
June 22nd, 2011, 01:55 PM
#4
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by paprica
My question is why?
Why do I need to fill my structure with zeros?
What is OPENFILENAME any different from any other WinAPI structure I initialized before and didn't use ZeroMemory?
Actually, you do not have to fill your structure with zeroes. Before that API call some members must NOT be zero.
You could simply set all members that you need one-by-one (as was shown above). But with a large structure, and if you know that most members should be set to 0 anyway, it is easier to use ZeroMemory() first and then set only non-0 members.
That also guarantees that if you did not specifically set some member value, it will be 0. And this is always better than some garbage value.
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
June 23rd, 2011, 05:00 AM
#5
Re: The ZeroMemory macro and OPENFILENAME
ZeroMemory(sizeof(ofn)) might cause a crash to your program.
Imagine you have compiled your program with a version of the include file where the size of OPENFILENAME is 40 bytes (I have not counted, this is an example).
And imagine you are running your program on an old Windows version where the size of OPENFILENAME is 32 bytes.
Then, if you ZeroMemory the 40 bytes of the 32-byte long structure, you write 0 in 8 bytes beyond the structure, and this might cause damages.
So you were right to ask yourself the question about ZeroMemory(sizeof(ofn)). My recommendation is: don't do that.
-
June 23rd, 2011, 06:39 AM
#6
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by olivthill2
ZeroMemory(sizeof(ofn)) might cause a crash to your program.
Imagine you have compiled your program with a version of the include file where the size of OPENFILENAME is 40 bytes (I have not counted, this is an example).
And imagine you are running your program on an old Windows version where the size of OPENFILENAME is 32 bytes.
Then, if you ZeroMemory the 40 bytes of the 32-byte long structure, you write 0 in 8 bytes beyond the structure, and this might cause damages.
So you were right to ask yourself the question about ZeroMemory(sizeof(ofn)). My recommendation is: don't do that.
Sorry, but this is just wrong. How would the run-time version of Windows affect the size of ofn determined at compile time?
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
June 23rd, 2011, 07:06 AM
#7
Re: The ZeroMemory macro and OPENFILENAME
ZeroMemory(sizeof(ofn)) might cause a crash to your program.
...
That crash (if any) is out of the responsibility of the developer who uses OPENFILENAME structure. It is the responsibility of the person who designs GetSaveFileName/GetOpenFileName functions and OPENFILENAME structure.
If he doesn't take care of backward compatibility of its API, then the crash described can be happen also without ZeroMemory call (for example the structure members and their meaning are totally changed in new version of the structure). Since MS stated, that their API keeps backward compatibility between old and new OS-es, the crash should not be happen. I guess (on old and new Windows) they will just look into the first member of the structure (lStructSize) and if it doesn't match to their expected/supported size, GetSaveFileName/GetOpenFileName function will return FALSE.
So you were right to ask yourself the question about ZeroMemory(sizeof(ofn)). My recommendation is: don't do that
Let's consider following situation.
ZeroMemory is not called and all members of OPENFILENAME structure are initialized individually.
In the future SDK new member is added into the structure and existing project is recompiled for newer version of the application.
As a result that new member will be uninitialized. So for safety it is always better to initialize the structure with 0-s before initializing members individually.
Last edited by Armen; June 23rd, 2011 at 07:10 AM.
-
June 23rd, 2011, 08:27 PM
#8
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by olivthill2
ZeroMemory(sizeof(ofn)) might cause a crash to your program.
If this is an issue, then the way out of it is to declare a global and static and initialize your local variables with it.
Code:
static OPENFILENAME dummy;
void foo()
{
OPENFILENAME local = dummy; // zero-initialized
// ...
};
Since globals and statics are zero initialized by default, then this sort of hack should work.
Regards,
Paul McKenzie
-
June 24th, 2011, 03:55 AM
#9
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by olivthill2
ZeroMemory(sizeof(ofn)) might cause a crash to your program.
No, ZeroMemory(sizeof(ofn)) will not cause a crash of your program but a compiler error because ZeroMemory macro requires 2 arguments.
-
June 24th, 2011, 04:00 AM
#10
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by Paul McKenzie
If this is an issue, then the way out of it is to declare a global and static and initialize your local variables with it.
Code:
static OPENFILENAME dummy;
void foo()
{
OPENFILENAME local = dummy; // zero-initialized
// ...
};
Since globals and statics are zero initialized by default, then this sort of hack should work.
Regards,
Paul McKenzie
And what about OPENFILENAME local = {0}; ?
-
June 24th, 2011, 05:49 AM
#11
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by ovidiucucu
And what about OPENFILENAME local = {0}; ?
Yes, that will work also.
Regards,
Paul McKenzie
-
June 24th, 2011, 06:02 AM
#12
Re: The ZeroMemory macro and OPENFILENAME
 Originally Posted by paprica
I noticed that every GetSaveFileName/GetOpenFileName example on the web uses the ZeroMemory macro after initializing the OPENFILENAME structure, like this:
Code:
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(ofn));
My question is why?
Why do I need to fill my structure with zeros?
What is OPENFILENAME any different from any other WinAPI structure I initialized before and didn't use ZeroMemory?
The question is really a general one.
When you declare a local variable of any type, unless you're dealing with C++ and the type has a constructor, the values are uninitialized. Since OPENFILENAME is a 'C' type with no user-defined constructor, then declaring an OPENFILENAME within a block of code gives you an OPENFILENAME filled with junk values.
So let's say you didn't initialize all the members, and you send this OPENFILENAME to a function that you have no control over and you didn't write, i.e. a Windows API function. The API function then looks at the OPENFILENAME you passed, and it uses these bogus values to do whatever it needs to do. Then what you have now is an API function that acts erratically, depending on what junk values were in the OPENFILENAME at the time.
You will know when something isn't right when your program behaves differently when you call GetOpenFileName( ). You may have the program working on some days, bombing out on other days, failing on one machine, but working on another machine, etc. Anytime you have a Windows API function not behaving consistently between runs, always check if you're sending a struct, whatever that struct is (in this case it's OPENFILENAME) is initialized with known values.
So that's why ZeroMemory() is called -- to make sure that the struct uses known values, and no invalid values throws off the routine that is going to use the struct. As ovidiucucu pointed out, you can really initialize the struct (which you did not do in your example) by truly initializing it to 0.
Code:
OPENFILENAME ofn = {0};
But again, you should keep this in mind for any struct you use that eventually will be passed to another function to be processed. If that struct has the potential to have uninitialized members, then you need to be very careful and determine if those uninitialized values can potentially cause erratic behaviour in the program. When in doubt, then set these members to some value (usually the documentation will tell you what these should be set for).
Regards,
Paul McKenzie
Last edited by Paul McKenzie; June 24th, 2011 at 06:04 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|