Skip to main content
gamedev.net
🔒 Locked

vtable problem

Started by michaweyel 6 replies 850+ views
Original Post
michaweyel
michaweyel
Hello, I have a C++ base class that has (among others) a virtual function. It is NOT pure virtual and the base class provides an implementation of the function. All derived classes overrride this function. Now, whenever I create an object of one of the derived classes and call the function, everything works fine. However, when I create a base class object and call the function, my program crashes with a memory error (Unhandled exection...Access violation...the usual windows error message box). When I look at the base class object in the debugger, the __vfptr member (I assume it is the pointer to the vtable) points to NULL. All the derived class objects have the __vfptr member correctly initialized. Does anybody know what could be the problem? (btw I'm using winXP and MS Visual Studio 2005) -Michael
stylin
stylin
virtual function pointer. Have you determined where in the code the crash occurs? Can you post a code snippet? How are you defining the base class object? How are you calling the base class member?
:stylin: "Make games, not war." "...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
michaweyel
michaweyel
hmmm...just found out that the problem is a bit more complicated. I'll try to explain.

What I have is something like:

class A
{
virtual unsigned int f() { return 1; }
void g() { int n = f(); }
}

class B : public A
{
unsigned int f() { return 2; }
}


Doing the following works fine:

A objectA;
B objectB;
int a = objectA.f();
int b = objectB.f();


However, the program crashes when I do one of the following

A objectA;
objectA.g();

B objectB;
objectB.g();


And it always crashes when f() is to be called inside g().
stylin
stylin
Posting your actual code might help. Do you have classes or structs (did you forget to include public: in your code snippet)?
:stylin: "Make games, not war." "...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
michaweyel
michaweyel
yeah, I have classes, sorry, I forgot public: (actually, the relevant functions are all public)

okay, my class looks like this:

  dataContainerRaw();  dataContainerRaw(unsigned int resourceId,           const char * pData, unsigned int length );  dataContainerRaw(const std::string & s) { interpret(s); }  /// returns the total number of bytes of a complete data container  unsigned int size() { return totalSize; }  /// returns the number of unspecified bytes available for user content  virtual unsigned int nData();  /// returns a pointer to the data container's content  const char * data() const { return m_data.chars.m_chars; }  /// sets the data container's content  void data(const char * pData, unsigned int length);  /// sets the data container's content to a string  void data(const std::string & s) { data(s.c_str(),static_cast<unsigned int>(s.size()+1)); }



the implementation of nData() and data(const char * pData, unsigned int length);
unsigned int dataContainerRaw::nData(){	return totalSize - headerSize;}/// sets the data container's contentvoid dataContainerRaw::data(const char * pData, unsigned int length) {  //HERE IT CRASHES	int nd = nData();	int min = min(nd, length);  memcpy(m_data.chars.m_chars,pData, min);}


and this is how I call the functions

  int i = 0;  dataContainerRaw resource;  resource.data("blah");

[/source]
michaweyel
michaweyel
my own stupidity, as usual...

in my base classes constructor, I was doing memset(this, 0, ...), so obviously, all the values in the vtable were NULLED as well...However, I also call the base class constructor in the constructors of the derived classes, but they work fine. So it seems that the vtable of the derived classes is initialized after the base classes constr has been called.

Anyway, thanks everybody for looking into this.

-Michael
Evil Steve
Evil Steve
Quote:
Original post by michaweyel
So it seems that the vtable of the derived classes is initialized after the base classes constr has been called.
Yup. That's why you can't use virtual functions in your constructor.

jpetrie
jpetrie
And also why memset(this,...) is naughty.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.