Skip to main content

virtual function table pointers and memset

  • Still a bit to go but finishing up the chico of the dead game, about a week left? event spent some time improving the quality of the first part of the game experence (added help)

  • well, took 5 hours to write my own morph plugin for max, but then took 2 days to change the pipeline, engine and animation for stream based morphing.
    and so the first thing to make was a shalug, half shark, half slug. what else is morphing…

  • First pass of the assets is almost done (evironemnt, some props, 3 player models and 5 zombies are done. one zombie and 3 small creatures left)
    Code is also getting done, minus the occasional task from hell such as 'rewrite collision system…

  • Started to implement game flow over the place holder assets, so have seen ingame cinematics and the simple scripting sequence work.
    Today finished one of the three player models, added frustum culling and linked up the missing bits for game…

  • Day 15 game dev, the zombie can now fight back which makes thing seem a bit more fair, also made it a lot tougher to kill the zombies.
    Title screen and starting a new game are done. now to make place holder art for the rest of the game.

  • Still working on iPhone, now have opengles2 support for my pipeline (shaders)
    finished up the goldfish project, and having a break from the cute stuff to do something violent, like shoot zombies.
    zombie is a performance test, though still…

  • Took a break from programming to do some artwork, and kind of happy with the result of an afternoon mucking about with normal maps. possibly should learn mudbox or zbrush, but found a workflow that suits me, even if i get to swear about polygon…

  • well, that is a way to spend my time.
    had another go at asset pipeline, using what i had learnt over the last few months and getting the information to the engine for the shaders, as well as preserving non shader rendering.

    excitement…

  • well, it is not so much that it is finished, it is more that i'm moving on and not working on it further.

    Nice to wrap something up, annoying the difference in quality of what you want to get done and what you can realistically get done.…

  • That took a bit longer than expected, but now have my own 3dstudio max exporter supporting biped, physique, scene graph, materials and animation. Also happen to have a win32/ iphone game engine that supports skinning.
    (morphing is mostly done…

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