By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,426 Members | 3,152 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,426 IT Pros & Developers. It's quick & easy.

memset on structs with non-PODs

P: n/a
Dear all,

I have an existing piece of code with a struct with some PODs.

struct A
{
int x;
int y;
};

This struct is created somewhere and initialized via a memset.

A a;
memset(&a,0,sizeof(A));

Now I want to extend the structure with an object, e.g a vector:

struct A
{
int x;
int y;
std::vector<int> z;
};

The sequence

A a;
memset(&a,0,sizeof(A));

would be fatal now, because I overwrite the instanciated vector a.z.
In reality the struct is very huge with a bunch of PODs inside, so using a
ctor would be possible, but quite a lot of work. (I am also scared to miss
something). How would you proceed to avoid the devastating memset?
I thought of kind of

struct A
{
int x;
int y;
int no_memsetbeyond_this_point;
std::vector<int> z;
};

and

A a;
memset(&a,0,&a.no_memsetbeyond_this_point-&a);

It is not really nice, but I have to avoid as much code-rework as possible
for the moment.

Kind regards,
Patrick
Jan 19 '06 #1
Share this Question
Share on Google+
14 Replies


P: n/a
* Patrick Kowalzick:
Dear all,

I have an existing piece of code with a struct with some PODs.

struct A
{
int x;
int y;
};

This struct is created somewhere and initialized via a memset.

A a;
memset(&a,0,sizeof(A));

Now I want to extend the structure with an object, e.g a vector:

struct A
{
int x;
int y;
std::vector<int> z;
};
When you have public non-POD members you need to redesign.

The sequence

A a;
memset(&a,0,sizeof(A));

would be fatal now, because I overwrite the instanciated vector a.z.
In reality the struct is very huge with a bunch of PODs inside, so using a
ctor would be possible, but quite a lot of work. (I am also scared to miss
something). How would you proceed to avoid the devastating memset?


When you a "very huge" struct you need to redesign.

But possibly you need to practice that on some smaller test programs
first.

For now, rename the orginal struct to PodA,

struct PodA { ... };

then derive struct A from that,

struct A: PodA
{
A(): PodA() {}
std::vector<int> z;
};

and also check that your compiler supports default-initialization of
POD's (unfortunately some don't).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jan 19 '06 #2

P: n/a
Hello Alf,
struct A
{
int x;
int y;
std::vector<int> z;
};
When you have public non-POD members you need to redesign.


Normally I'd never use struct for more complex things :).
In reality the struct is very huge with a bunch of PODs inside, so using
a
ctor would be possible, but quite a lot of work. (I am also scared to
miss
something). How would you proceed to avoid the devastating memset?


When you a "very huge" struct you need to redesign.


Hmm, might be. Lets say very huge in this context is nothing elses than: I
do not want to initialize all the members.
For now, rename the orginal struct to PodA,

struct PodA { ... };

then derive struct A from that,

struct A: PodA
{
A(): PodA() {}
std::vector<int> z;
};
Perfect. Thats a rather good solution. Anyway for this case I will change to

struct PodA
{
PodA() { memset(this,0,sizeof(PodA)); }
...
};

struct A: PodA
{
std::vector<int> z;
};

This is not nice (ok it is ugly), but closer to the original code.
and also check that your compiler supports default-initialization of
POD's (unfortunately some don't).


I can not, as support for different compiliers has to be assured.

Thanks, that's really good solution.

Regards,
Patrick
Jan 19 '06 #3

P: n/a
On Thu, 19 Jan 2006 14:57:34 +0100, "Patrick Kowalzick"
<pa***************@mapandguide.de> wrote:
Dear all,

I have an existing piece of code with a struct with some PODs.

struct A
{
int x;
int y;
};

This struct is created somewhere and initialized via a memset.

A a;
memset(&a,0,sizeof(A));

Now I want to extend the structure with an object, e.g a vector:

struct A
{
int x;
int y;
std::vector<int> z;
};

The sequence

A a;
memset(&a,0,sizeof(A));

would be fatal now, because I overwrite the instanciated vector a.z.

<snip>

You may create a non-virtual base class with only POD data and inherit
from it. In such a way, you could still a memset, but only with thiis
base class.

struct A_
{
int x;
int y;
};

struct A:public A_
{
A() {memset(static_cast<A_ *>(this),0,sizeof(A_);}
std::vector<int> z;
};

Regards,

Zara
Jan 19 '06 #4

P: n/a

Patrick Kowalzick wrote:
Dear all,

I have an existing piece of code with a struct with some PODs.

struct A
{
int x;
int y;
};

This struct is created somewhere and initialized via a memset.


[]

Overload memset() in the same header where A is declared:

void memset(A*, int, size_t);

Note that this overload won't be called if memset is invoked as:

memset(void*)&a, ...);

A more proper way would be to redesign the code, so that it don't do
memset on A's anymore.

Jan 19 '06 #5

P: n/a

Alf P. Steinbach wrote:
* Patrick Kowalzick:
Dear all,

I have an existing piece of code with a struct with some PODs.

struct A
{
int x;
int y;
};

This struct is created somewhere and initialized via a memset.

A a;
memset(&a,0,sizeof(A));

Now I want to extend the structure with an object, e.g a vector:

struct A
{
int x;
int y;
std::vector<int> z;
};


I have a follow on question to this. Given:

unsigned int const max_id = 5;
unsigned int const max_participants = 5;
struct some_struct
{ int some_param;
some_struct()
: some_param( -1) {}
};

struct some_other_struct
{ int some_var;
int some_size;
unsigned char* ptr;
some_other_struct()
: some_var(-1)
, some_size(-1)
, ptr(0)
{}
};

struct someImportantData {
unsigned int c_style_arr[ max_participants ];
some_struct c_style_arr2[ max_id ] [ max_participants ];
some_other_struct c_style_arr3[ max_participants ];
};
int main()
{
someImportantData sid;
for ( int idx(0); idx < max_participants; ++idx )
{
sid.c_style_arr[ idx ] = idx ;
}
typedef std::vector<unsigned int> UINT_VEC;
UINT_VEC myVec(&sid.c_style_arr[0],
&sid.c_style_arr[max_participants] );

UINT_VEC::iterator end = myVec.end();
for ( UINT_VEC::const_iterator it = myVec.begin(); it != end; ++it )
{
std::cout << *it << std::endl;
}

}

Now going from c_style_arr to a vector is easy (as shown below) .
How would I do the c_style_arr2 and c_style_arr3? Part of the issue
with c_sytle_arr2 is based on the fact that I'm still experimenting
with 2-d vectors.

In any event, thanks in advance.

Jan 19 '06 #6

P: n/a
Hello Maxim,
I have an existing piece of code with a struct with some PODs.

struct A
{
int x;
int y;
};

This struct is created somewhere and initialized via a memset.


[]

Overload memset() in the same header where A is declared:

void memset(A*, int, size_t);

Note that this overload won't be called if memset is invoked as:

memset(void*)&a, ...);

A more proper way would be to redesign the code, so that it don't do
memset on A's anymore.


The memset are not too often, so I kicked them :). But it seems to be a good
idea to overload memset, perhaps I missed one.....

void memset(A*, int, size_t)
{
assert( "Please, please do not use memset for this struct");
}

Hmm, or static_assert? Would something like this work as static assert?

// forward for allowed memsets
template < typename T > class memset_functor
{
public:
void * operator()( T* dest, int c, size_t count )
{
return memset(dest,c,count);
}
};

// forward for disallowed memsets
template <> class memset_functor< A >
{
public:
void * operator()( A *, int, size_t )
{
// STATIC_ASSERTION
}
};

template < typename T >
void * memset( T* dest, int c, size_t count )
{
return memset_functor<T>()(dest,c,count);
}

Looks funny. I will test this towmorrow :)

Regards,
Patrick
Jan 19 '06 #7

P: n/a

"Patrick Kowalzick" <pa***************@mapandguide.de> skrev i
meddelandet news:ne********************@proxy.mapandguide.de.. .
Hello Alf,
struct A
{
int x;
int y;
std::vector<int> z;
};
When you have public non-POD members you need to redesign.


Normally I'd never use struct for more complex things :).
In reality the struct is very huge with a bunch of PODs inside, so
using a
ctor would be possible, but quite a lot of work. (I am also scared
to miss
something). How would you proceed to avoid the devastating memset?


When you a "very huge" struct you need to redesign.


Hmm, might be. Lets say very huge in this context is nothing elses
than: I do not want to initialize all the members.
For now, rename the orginal struct to PodA,

struct PodA { ... };

then derive struct A from that,

struct A: PodA
{
A(): PodA() {}
std::vector<int> z;
};


Perfect. Thats a rather good solution. Anyway for this case I will
change to

struct PodA
{
PodA() { memset(this,0,sizeof(PodA)); }
...
};

But now you have a constructor, so it's not a POD anymore. :-(

This is not nice (ok it is ugly), but closer to the original code.


It is ugly!
Bo Persson

Jan 19 '06 #8

P: n/a
> Hmm, or static_assert? Would something like this work as static assert?

// forward for allowed memsets
template < typename T > class memset_functor
{
public:
void * operator()( T* dest, int c, size_t count )
{
return memset(dest,c,count);
}
};

// forward for disallowed memsets
template <> class memset_functor< A >
{
public:
void * operator()( A *, int, size_t )
{
// STATIC_ASSERTION
}
};

template < typename T >
void * memset( T* dest, int c, size_t count )
{
return memset_functor<T>()(dest,c,count);
}

Looks funny. I will test this towmorrow :)


Ok. I tried it, and it does not work.

The specialization memset_functor< A > will be instanciated, even if there
is no call "memset(A,int,size_t)". Like this the static assertion always
fails.

I use now an easier approach, which works on my compiler, but I am not sure
if it is bullet proof:

template < typename T >
void * memset( TTransferDistlibData2 * dest, T c, size_t count )
{
BOOST_STATIC_ASSERT(FALSE);
return NULL;
}

Calling memset(A,..) fails like this to compile.

Kind regards,
Patrick
Jan 20 '06 #9

P: n/a
Hello Bo,
Perfect. Thats a rather good solution. Anyway for this case I will change
to

struct PodA
{
PodA() { memset(this,0,sizeof(PodA)); }
...
};

But now you have a constructor, so it's not a POD anymore. :-(


Hmm, ok. I call it "public class with only PODs inside" :).
This is not nice (ok it is ugly), but closer to the original code.


It is ugly!


no choice.

Regards,
Patrick
Jan 20 '06 #10

P: n/a

"Patrick Kowalzick" <pa***************@mapandguide.de> skrev i
meddelandet news:ne********************@proxy.mapandguide.de.. .
Hello Bo,
Perfect. Thats a rather good solution. Anyway for this case I will
change to

struct PodA
{
PodA() { memset(this,0,sizeof(PodA)); }
...
};

But now you have a constructor, so it's not a POD anymore. :-(


Hmm, ok. I call it "public class with only PODs inside" :).


Ok, I didn't explain it properly:

If it's not a POD, you cannot use memset() on it.
That was the original problem! :-)
Bo Persson
Jan 21 '06 #11

P: n/a
Hello Bo,
Hmm, ok. I call it "public class with only PODs inside" :).
Ok, I didn't explain it properly:

If it's not a POD, you cannot use memset() on it.


Why not? I will take a look in the standard, now, but I was quite sure, that
adding a function to POD-struct will not change the memory structure of this
struct. I see no obvious reason, why this should be dangerous.

If it is dangerous there is still the soution Zara suggests...
That was the original problem! :-)


Not really. The problem was an inner class, which itself may initialize,
inside a structure which is overwirtten by a memset on the outer struct. The
initialization of the inner class is lost (and even worse the instance might
be invalid).

Kind regards,
Patrick
Jan 23 '06 #12

P: n/a
>>> Hmm, ok. I call it "public class with only PODs inside" :).

Ok, I didn't explain it properly:

If it's not a POD, you cannot use memset() on it.


Why not? I will take a look in the standard, now, but I was quite sure,
that adding a function to POD-struct will not change the memory structure
of this struct. I see no obvious reason, why this should be dangerous.


I think, a class with a ctor can still be a POD-class. There fore two cites
from the standard:

"(3.9.10) Arithmetic types (3.9.1), enumeration types, pointer types, and
pointer to member types (3.9.2), and cv-qualified versions of these types
(3.9.3) are collectively called scalar types. Scalar types, POD-struct
types, POD-union types (clause 9), arrays of such types and cv-qualified
versions of these types (3.9.3) are collectively called POD types."

"(9.0.4) {...} A POD-struct is an aggregate class that has no non-static
data members of type non-POD-struct, non-POD-union (or array of such types)
or reference, and has no user-defined copy assignment operator and no
user-defined destructor. Similary, a POD-union is an aggregate union that
has no non-static data members of type non-POD-struct, non-POD-union (or
array of such types) or reference, and has no user-defined copy assignment
operator and no user-defined destructor. A POD class is a class that is
either a POD-struct or a POD-union."

I have no other non-POD typed, nor a copy assignment, nor a dtor. So it is
still a POD? But what about a vtable? Might this still be a POD?

Regards,
Patrick
Jan 23 '06 #13

P: n/a
> I think, a class with a ctor can still be a POD-class. There fore two
cites from the standard:
Bullshit :).
"(3.9.10) Arithmetic types (3.9.1), enumeration types, pointer types, and
pointer to member types (3.9.2), and cv-qualified versions of these types
(3.9.3) are collectively called scalar types. Scalar types, POD-struct
types, POD-union types (clause 9), arrays of such types and cv-qualified
versions of these types (3.9.3) are collectively called POD types."

"(9.0.4) {...} A POD-struct is an aggregate class that has no non-static
data members of type non-POD-struct, non-POD-union (or array of such
types) or reference, and has no user-defined copy assignment operator and
no user-defined destructor. Similary, a POD-union is an aggregate union
that has no non-static data members of type non-POD-struct, non-POD-union
(or array of such types) or reference, and has no user-defined copy
assignment operator and no user-defined destructor. A POD class is a class
that is either a POD-struct or a POD-union."

I have no other non-POD typed, nor a copy assignment, nor a dtor. So it is
still a POD? But what about a vtable? Might this still be a POD?


"[8.5.1.1] An aggregate is an array or a class (clause 9) with no
user-declared constructors (12.1), no private or protected non-static data
members (clause 11), no base classes (clause 10), and no virtual functions
(10.3)."

And for sure, read the FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-26.7

Thanks all a lot for you input in this thread. I hope I got it now.

Kind regards,
Patrick
Jan 23 '06 #14

P: n/a
Hello Alf,
For now, rename the orginal struct to PodA,

struct PodA { ... };

then derive struct A from that,

struct A: PodA
{
A(): PodA() {}
std::vector<int> z;
};

and also check that your compiler supports default-initialization of
POD's (unfortunately some don't).


I checked this. Some of my compilers support default-initialization, some
not :(. This is really sad.

So I use now this here (even if there is a difference to memset in the
result):

struct A_PODs{ ... };

struct A : public A_PODs
{
A()
{
static A_PODs zero_init = { 0 };
// static A_PODs zero_init = { }; // would be enough, but does not
work on all compilers.
*(static_cast< A_PODs * >(this)) = zero_init; // is this safe?
}
};
Kind regards,
Patrick
Jan 24 '06 #15

This discussion thread is closed

Replies have been disabled for this discussion.