Skip to main content

virtual function table pointers and memset

  • Was looking for a reason to learn sql, and was feeling the urge to play an oldschool pen and paper rpg.

    didn't like gurps licence, nor dnd's 'open' source licence, then while looking around, found legendary quest, which is kind of neat.…

  • somewhat random, got up to speed with SDL (simple media layer) to see what it could do for me to make my life easier, also rewrote my game engine to be a lot more generic and support unittest.

    grey image is having fun bluring the depth…

  • Note. Not my base mesh and texture, purchased a highres model from turbosquid (20000+ vertex, several 4098x4098 textures) and reduced it to 600 vert and a 2048x2048 texture page (for diffuse, alpha, normal and specular maps)

    was currious…

  • Have never done that much database/php stuff, but was currious if you could make a game using javascript/canvas rather than flash.
    this seemed fine till trying to get Internet Explorer to work, in which case i would like to think flash works…

  • Made an update for the Bikini Beach Volley Ball game, 4 new girls, one new location.
    Screen shots are from iPhone and iPad.

  • a week of prototyping (6 prototypes), 1 of which failed and not included, another of which i am still working on and not online yet (procrastinating by blogging rather than finishing it)

    Seems prototyping is the popular thing to do at the…

  • capture of iPhone gameplay of my lattest game, Bikini Beach Volleybal

  • and so the quick 2 week project to recover from a big project/ experement with stencil shadows is now up to the 4 week mark.
    wrote a gui/ font system and tools pretty much from scratch which is a good way of making a 2 week project take 4…

  • because i can, though the play mechanic is pretty much pong, and after spending the day making animation i'm kind of wiped out to type anything interesting.

    the main photo, had one of my female friends critique the bikini girls appearance…

  • Bit of a slow week, finished 'chico of the dead' (once it is available in the app store i get to start promoting it, fun) and during the recovery time after a big project, tidied up some randoms bits of tech, simplified renderer, and added…

Submitted by davidcoen on
Forum

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

Submitted by Daemin on Thu, 24/07/03 - 10:52 PM Permalink

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.

Submitted by redwyre on Fri, 25/07/03 - 8:54 PM Permalink

you might be able to do something with an unnamed struct and/or an unnamed union and memset that

Submitted by redwyre on Sat, 26/07/03 - 7:35 AM Permalink

union
{
char dummy;
struct
{
int a,b,c;
float x,y,z;
};
};

hmmmm...

Submitted by Daemin on Sat, 26/07/03 - 7:40 AM Permalink

Why bother when you can jsut explicitly set every value... and you can reserve memset for the larger arrays and such.

Submitted by redwyre on Sat, 26/07/03 - 8:01 AM Permalink

yeah, generally if the initialiser list is too large, it's time to rethink the structure anyway

Submitted by davidcoen on Sat, 26/07/03 - 9:52 AM Permalink

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

Submitted by redwyre on Wed, 13/08/03 - 2:18 AM Permalink

yay, throw away that dirty code!

malloc is evil, if you are using it in C++ code I'll have to send some of my ninja's after you(trained in the deadly art of code-fu).

Submitted by Blitz on Wed, 13/08/03 - 4:58 AM Permalink

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

Submitted by Daemin on Wed, 13/08/03 - 7:24 AM Permalink

But the number of VFP tables depends on how many objects with virtual function a certain class has in its hierarchy.

Submitted by pragma x on Wed, 13/08/03 - 2:48 PM Permalink

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]

Submitted by redwyre on Wed, 13/08/03 - 8:53 PM Permalink

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..

Posted by davidcoen on
Forum

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


Submitted by Daemin on Thu, 24/07/03 - 10:52 PM Permalink

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.

Submitted by redwyre on Fri, 25/07/03 - 8:54 PM Permalink

you might be able to do something with an unnamed struct and/or an unnamed union and memset that

Submitted by redwyre on Sat, 26/07/03 - 7:35 AM Permalink

union
{
char dummy;
struct
{
int a,b,c;
float x,y,z;
};
};

hmmmm...

Submitted by Daemin on Sat, 26/07/03 - 7:40 AM Permalink

Why bother when you can jsut explicitly set every value... and you can reserve memset for the larger arrays and such.

Submitted by redwyre on Sat, 26/07/03 - 8:01 AM Permalink

yeah, generally if the initialiser list is too large, it's time to rethink the structure anyway

Submitted by davidcoen on Sat, 26/07/03 - 9:52 AM Permalink

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

Submitted by redwyre on Wed, 13/08/03 - 2:18 AM Permalink

yay, throw away that dirty code!

malloc is evil, if you are using it in C++ code I'll have to send some of my ninja's after you(trained in the deadly art of code-fu).

Submitted by Blitz on Wed, 13/08/03 - 4:58 AM Permalink

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

Submitted by Daemin on Wed, 13/08/03 - 7:24 AM Permalink

But the number of VFP tables depends on how many objects with virtual function a certain class has in its hierarchy.

Submitted by pragma x on Wed, 13/08/03 - 2:48 PM Permalink

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]

Submitted by redwyre on Wed, 13/08/03 - 8:53 PM Permalink

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..