4

I've seen examples where ZeroMemory is used (mainly with windows and directx structs), but other times it is not used. When should I ZeroMemory a struct?

pghazanfari
  • 515
  • 2
  • 6
  • 8

7 Answers7

6

ZeroMemory simply fills the memory of the struct with 0's, what essentially means that every value of the struct is set to 0. This is necessary if you don't set all values of the struct a custom value before passing it to for example a API function. When creating the struct there are unspecified values in each field - this causes undefined behaviour in the function thats then accessing the fields of the struct.

maxdev
  • 2,491
  • 1
  • 25
  • 50
  • 1
    They can't be "misinterpreted". Even reading an uninitialized value is undefined behavior making your program mal-formed. – pmr Apr 07 '14 at 11:30
  • They can, because the function that receives the values assumes that these values are correct. It has no way to check if these values were set by the user or if they are the initial values of that memory region (which might be whatever). – maxdev Apr 07 '14 at 16:27
  • You seem to not understand unintialized values in C. Accessing them is undefined behavior. You don't get misinterpretation, just plain undefined behavior. – pmr Apr 07 '14 at 16:35
  • I think you maybe mean *pointers*, not *values*... For example `int i;` has a value, but it can be anything that just already was on the position this value got on the stack, this does not cause any behavior, except of giving you just any value. But, creating an `int* i;` and accessing it's values is in fact undefined behavior.. – maxdev Apr 07 '14 at 16:39
  • 1
    No, I mean any value including pointers. Read http://stackoverflow.com/questions/11962457/why-is-using-an-uninitialized-variable-undefined-behavior-in-c?rq=1 – pmr Apr 07 '14 at 17:41
  • 1
    Okay, you are right :) *(edited the question according to that info)* – maxdev Apr 08 '14 at 14:59
5

You should pretty much never do this in C++ unless some external API you're programming to asks you to do so (which will likely be for old Windows C APIs). There are ways to initialise data using default constructors, and that way if the data types the memory houses are changed the construction will automatically adjust. Use of ZeroMemory to initialise data is fragile.

Interesting, Microsoft mention that ZeroMemory might not even work in this documentation for SecureZeroMemory:

Use this function instead of ZeroMemory when you want to ensure that your data will be overwritten promptly, as some C++ compilers can optimize a call to ZeroMemory by removing it entirely.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
4

If you're creating C++ program, then do not use ZeroMemory. Use constructor and initialize list to init fields. BTW, in C++11 you can use this syntax:

struct A {
    int x = 0;
    int y = -1;
    int z = 42;
};

instead of "old-style"

struct A {
    int x;
    int y;
    int z;
    A() : x( 0 ), y( -1 ), z( 42 ) {}
};
borisbn
  • 4,988
  • 25
  • 42
3

ZeroMemory(&a, sizeof(a)) is equal to memset(&a, 0, sizeof(a));. It just fill memory with zero.

But you must notice a should be POD-data. that is, you must not do this:

std::string str;
ZeroMemory(&a, sizeof(a)); // never!!

You should use ZeroMemory and memset to POD-data. (If you don't know about POD-data, it's just like C-style struct.) If you do memset to non-POD, undefined behavior will be coming..

ikh
  • 10,119
  • 1
  • 31
  • 70
  • The real problem is that one _can_ `memset` non-PODs, but it yields undefined behaviour. It may work, it may not, but in any case, it makes for non-portable and highly fragile code. – Sebastian Mach Apr 07 '14 at 11:15
  • Indeed. The problem in your post, you write `that is, you can't this:` and `// error!!`, but neither can't you not do that, nor does it yield an error. You perfectly can `memset` everything in C++, but on a _legal_ basis, this gives undefined behaviour. – Sebastian Mach Apr 07 '14 at 11:19
  • @phresnel Um.. I intend to "you must not; if you do this, suck error will occur", But I agree that there's some misleading. I'll edit. – ikh Apr 07 '14 at 11:23
  • Looking better now :) – Sebastian Mach Apr 07 '14 at 11:44
1

When you create a structure (especially when working with old Win32 API legacy code) your allocated structure can have garbage in it, since those Win32 structures have no real constructor. So this is a way to initialize your structure to default values.

Ferenc Deak
  • 34,348
  • 17
  • 99
  • 167
1

You zero a struct when there's a lot of values to fill out and zeros are valid values for the parts you're not interested in setting manually. Sorry if that's kinda vague, but that's basically how it is (e.g. you have a struct full of pointers that are allowed to be NULL for optional values, and you only want to set a couple of them).

Remember that if you don't set struct members to anything, in most situations they're filled with garbage when you create them (in C++ a struct may have a constructor that already takes care of this for you though).

ZeroMemory is a windows thing though, the standard equivalent is memset(ptr,0,size). It's not something you need often in C++, although it pops up in C quite a bit (although you can write constructor like functions in C too, which I'd recommend you to do).

Cubic
  • 14,902
  • 5
  • 47
  • 92
1

It is compiler dependend, new gcc automaticly zero structs but older ones have random values ( according to maxdev).

take a look at this thread: When zeroing a struct such as sockaddr_in, sockaddr_in6 and addrinfo before use, which is correct: memset, an initializer or either?

Community
  • 1
  • 1
flotto
  • 535
  • 5
  • 17