views:

186

answers:

4

This morning we found an old chunk of code that was causing a library call to crash.

struct   fred
{
    int     a;
    int     b;
    int     c;
};

fred     fred[MAX_SIZE+1];

memset( fred, 0, sizeof(fred) * MAX_SIZE+1 );

It appears that the sizeof(fred) may have been the full array size, rather than the structure size, as it was overwriting a great deal of memory.

The fact that it compiled without warning on several different systems seemed odd.

Is there a correct semantic for this case where the type and variable name are colliding? or is this some sort of undefined behavior? or just a defect?

I haven't been been clever enough to find anything on Google or our language help.

Thanks

Evil

+2  A: 

Shouldn't this be sizeof(fred)*(MAX_SIZE+1) since your array is MAX_SIZE+1 long?

martiert
Yes. That certainly is additional evil. +1
EvilTeach
+13  A: 

Number one would be, don't do this as it's confusing - but you've already discovered this.

The variable hides the name of the struct, but you can still use struct fred to refer to the type.

e.g.

fred     fred[MAX_SIZE+1];

memset( fred, 0, sizeof(struct fred) * (MAX_SIZE+1) );

Alternatively, why not just use the size of the complete object. That way your memset call is robust in the face of changes to either the array size or type. You can do:

memset( fred, 0, sizeof fred );

You must have the parentheses when using a type id with sizeof but it's not needed when you use an object.

Charles Bailey
+1  A: 

When you define the variable, it hides the name of the type, so yes, when you do sizeof(fred), you're getting the size of the array, not the size of the struct. it's pretty easy to verify this by simply printing out sizeof(fred).

The short answer, however, is just: "don't do that."

Jerry Coffin
A: 

With the exception of run-time sized cases, the typical idiomatic way to use memset (as well as memcpy, malloc, etc.) is to do

memset(dst_ptr, 0, sizeof *dst_ptr);

or, equivalently,

memset(&dst_object, 0, sizeof dst_object);

Which is how it should have been used in this case as well

memset(&fred, 0, sizeof fred);

and the problem with the name conflict would not arise. The memset(fred, 0, sizeof fred) variant will work as well.

AndreyT