not that i write code (cough) but was writing something suspiciously big over several days, in vc6, and today stated to use memset in my object constructors (got bored initilising stuff to 0).
was also using virtual functions in some objects, and after a while i stated to wonder where the virtual table pointer for the compiler to know which 'virtual function table' the base object was using, as it would be really impressive if it was outside the object, as each base pointer needs some unique way of knowing _which_ table to use
and now i'm currently having a break, as just steped through some code, and the virtual function table pointer seems to be zeroed by a call to memset(this,0,sizeof(KeyObj))
not happy.
summary, don't use memset in constructors of classes with virtual functions. if i read this before, i now know to pay attention to it.
DSC
thanks for comments everyone. was just surprised that the vtp didn't behave like malloc base (which i think puts a link list and flag infront of any memory returned...)
good point redwyre about not letting classes get too big (though unnamed struct in class looks evil :) i like evil.
threw out a days worth of codeing just to redesign it tomorrow, and even went back to clean up one of my base classes
//slightly disturbed buy redwyre having a GUID
If i understand you correctly...
It doesn't behave like malloc, because the memory returned by malloc is allocated natively by the operating system. VFP tables are handled at the application level, and memset etc. are handled at the OS layer and so have no knowledge of the app (and vfp table)...
Perhaps a C++ version of memset could be created to handle VFP tables :P
I think thats about right.
CYer, Blitz
Two Possible Solutions
I'm not entirely sure about this, but you may be able to rely on the fact that (most/all?) compilers will layout the internal fields of the struct/class in the order they are declared. If you memset the area between the first and last declared members (inclusive), you can effectively set the data area of the class. This technique will also have the side-effect of clearing any internal padding between members, which may or may not be desireable.
Note that we don't use 'sizeof' since it returns the memory area *including* any trailing padding (and of course the space occupied by the class' v-table).
Lack of supporting polymorphism aside, this should do the trick.
[code]
// macro shamelessly ripped off from microsoft
#define offsetof(s,m) (size_t)&(((s *)0)->m)
class Foobar
{
int a; // first member
char b;
float c;
double d; // last member
public:
virtual ~(){} // we want a class w/a vtable
static Clear(Foobar* pFoobar)
{
size_t ofsFirst = offsetof(pFoobar,a);
size_t ofsLast = offsetof(pFoobar,d) + sizeof(d);
memset(pFoobar + ofsFirst,0,ofsLast - ofsFirst); }
};
void main()
{
Foobar a;
Foobar::Clear(a);
}
[/code]
Another way would be to override the new operator, which may not be desireable but is by far less of a hack. This works well since the allocation *has* to ocurr before the constructor can run, and before the vtable can even be assigned to the newly allocated slice of memory. Of course, this won't help any statically declared objects that never call 'new'.
[code]
void* operator new(size_t size)
{
void* p = malloc(size);
memset(p,0,size);
return(p);
}
// 'delete' included since some compilers complain when you don't
// implement a matching 'delete' for your overidden 'new'.
void operator delete(void* p)
{
free(p);
}
[/code]
offsetof is part of the standard () :)
another alternative (just FYI, this is all getting to be quite hackish):
template< class Ty > class ExplicitDefaultCtor
{
proteced:
Ty m_object;
public:
ExplicitDefaultCtor() : Ty() { }
operator Ty& () { return m_object; }
operator const Ty& () const { return m_object; }
};
class Foo { ExplicitDefaultCtor foo; }
actually, I think vc7.0/7.1 calls the default constructor of built in types now, so none of this should be nessisary..
Yeah, tha's one of those big no-no's, to use memset to set all of an object's contents to 0. It's okay to do it in plain old C code because they have no such thing built in, but not in C++.
Generally though an object has a vfpt (Virtual Function Pointer Table) if the class has inherited or has any virtual methods. It will have more than one of these pointers and tables if it has inherited from more than one class containing virtual functions.