| | |
Yet Another Vtable Problem
Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
![]() |
•
•
Join Date: Nov 2008
Posts: 4
Reputation:
Solved Threads: 0
Hi
So I've been developing this game for a game design class for most of the semester. While I'm not new to C++ and Object Oriented Design, the theory of it is often a lot easier to comprehend and know than the actual application of it. Needless to say, I've run numerous problems throughout the development of my game, most being surmountable.
However, my next goal is to get the code leak free via valgrind on Linux. Unfortunately, I've been developing on windows using Dev-Cpp and the Mingw compiler, and this has spawned some problems. While my code compiles and runs on Windows, when I compile using G++ on Linux, I'm getting the dreaded...
I've done research into what the problem might be, I've visited the GCC FAQ entry about it, I've read accounts on this board. I've encountered this before, and it came from failing to implement a purely virtual function in some manner (Stub or full implementation) in a derived class. I've read over the code of the classes the error involves, and this does not seem to be the case. I've also been told that this error can come up when "the destructor is not adequately defined," but that not a concrete enough explanation as to what's going on for me.
To try to circumvent this problem, I tried making every function of the base class that was virtual pure-virtual, as to force a definition for each function in each derived class, stub or fully implemented, also in hopes of forcing the vtable for each class into its object file, but much to no avail. So at my wits end, I've come to this forum hopefully to find some answers. Are there any other things that such an error can result from? Or any advice or pointers that can be given?
Let me know if I should post my code, as I'm hesitant to because it will be four classes (Base, Derived, More Derived), a lot of code, and I'm not sure if I should omit comments/functions definitions/or what.
Thanks in advanced,
Yates Monteith
So I've been developing this game for a game design class for most of the semester. While I'm not new to C++ and Object Oriented Design, the theory of it is often a lot easier to comprehend and know than the actual application of it. Needless to say, I've run numerous problems throughout the development of my game, most being surmountable.
However, my next goal is to get the code leak free via valgrind on Linux. Unfortunately, I've been developing on windows using Dev-Cpp and the Mingw compiler, and this has spawned some problems. While my code compiles and runs on Windows, when I compile using G++ on Linux, I'm getting the dreaded...
•
•
•
•
undefined reference to `vtable for class'
undefined reference to `typeinfo for class'
To try to circumvent this problem, I tried making every function of the base class that was virtual pure-virtual, as to force a definition for each function in each derived class, stub or fully implemented, also in hopes of forcing the vtable for each class into its object file, but much to no avail. So at my wits end, I've come to this forum hopefully to find some answers. Are there any other things that such an error can result from? Or any advice or pointers that can be given?
Let me know if I should post my code, as I'm hesitant to because it will be four classes (Base, Derived, More Derived), a lot of code, and I'm not sure if I should omit comments/functions definitions/or what.
Thanks in advanced,
Yates Monteith
•
•
Join Date: Nov 2008
Posts: 397
Reputation:
Solved Threads: 72
Yes, this case I would post the code. I figure that (a) you have actually googled this. (b) and tried some testing.
(c) your using a compiler that give better error messages that VC++.
However, this is not a completely uncommon error so I would like to explain what it normally means and if that doesn't fix it then please put some code up.
the destructor not adequately defined, normally means that you have a pointer that you cannot find the vtable back to the base.
E.g. consider class Base; class A : public Base; class B : public A;
No in a separate file you define stuff that uses ptrs/ref or B, and those ptrs get deleted OR those refs get moved out of scope. You don't have sufficient includes in the file, but you have pre-definitions. Then you have an implicit/direct call to a destructor that needs to call A and Base destructor. gcc can't resolve that.
So I AM GUESSING!!! that the error is in the lack of an include.
However, some code is going to help here so I think some posting is in order. If you have large methods maybe strip them down.
(c) your using a compiler that give better error messages that VC++.
However, this is not a completely uncommon error so I would like to explain what it normally means and if that doesn't fix it then please put some code up.
the destructor not adequately defined, normally means that you have a pointer that you cannot find the vtable back to the base.
E.g. consider class Base; class A : public Base; class B : public A;
No in a separate file you define stuff that uses ptrs/ref or B, and those ptrs get deleted OR those refs get moved out of scope. You don't have sufficient includes in the file, but you have pre-definitions. Then you have an implicit/direct call to a destructor that needs to call A and Base destructor. gcc can't resolve that.
So I AM GUESSING!!! that the error is in the lack of an include.
However, some code is going to help here so I think some posting is in order. If you have large methods maybe strip them down.
•
•
Join Date: Nov 2008
Posts: 4
Reputation:
Solved Threads: 0
Hi!
Thanks for the reply. After reading your post and looking through my code, I think that could possibly be the problem. In my more-derived class, I do have a reference to another class which could be calling the reference out of scope. I guess I'll start off with a description of the hierarchy in question, then post the code with some functions truncated.
My basest class is Drawable. It represents objects which have (Read: Private Variables) an x,y coordinate and a x,y velocity. It has a set of non-virtual accessor/mutator functions for speed/coordinates/etc, and a set of pure-virtual functions. I mentioned why these functions are pure virtual in the second post.
Duck is a derived class of Drawable. It has a few other private variables, including a vector of type Frame (Another derived of drawable, different hierarchy), a vector of type bullet (A derived of sprite, sprite derived from Drawable), and a couple other primitive data types. It also has all the pure-virtual functions from Drawable defined. Here's the code:
Finally, SmartDuck is a derived class of Duck. It only overloads the Update and Draw functions, inheriting everything else, as is. It has a reference to another class (Player, so it can get data access), along with an enumerator, and another primitive in its private section. There are a couple things commented out in the header, those are purely for debugging purposes.
Finally (Sorry, this is getting a little absurd), we have the Player class, immediatly derived from Drawable.
There errors I'm getting are:
And here is the relevant code for those areas:
Nota Bene: the player object is Drawable*, the ducks object is std::vector<Duck*>
So it seems my errors are coming from Construction and trying to cast pointer objects. The obvious thought is, why not take out the cast in fragDucks? Well, unfortunately, I've introduced a fairly long polymorphic hierarchy (There are still 4 or so classes I haven't posted, but are working fine), and if I don't do the cast, I risk referencing a null pointer, or accessing a function not defined for the class player currently represents.
So I'm sorry this got so long, but you've been very helpful so far, and I appreciate any further time you put into looking at my code. Hopefully it doesn't make your eyes bleed too badly.
Thanks for the reply. After reading your post and looking through my code, I think that could possibly be the problem. In my more-derived class, I do have a reference to another class which could be calling the reference out of scope. I guess I'll start off with a description of the hierarchy in question, then post the code with some functions truncated.
My basest class is Drawable. It represents objects which have (Read: Private Variables) an x,y coordinate and a x,y velocity. It has a set of non-virtual accessor/mutator functions for speed/coordinates/etc, and a set of pure-virtual functions. I mentioned why these functions are pure virtual in the second post.
C++ Syntax (Toggle Plain Text)
/* Drawable Class Header */ /* Preprocessor Directives */ #ifndef DRAWABLE__H #define DRAWABLE__H /* Necessary Libraries */ #include <SDL/SDL.h> #include <vector> #include <string> #include <iostream> #include <cmath> #include "frame.h" #include "drawable.h" /* Global Constants*/ const float BACKGROUND_SPEED = 50.0; const float PLAYER_SPEED = 5.0; const int WIDTH = 670; const int HEIGHT = 303; const float COLLISION_DISTANCE = 35; const float MAX_DISTANCE = 250; const int EXPLOSION_SPEED = 30; const float DUCK_XSPEED = 30; class Drawable { public: Drawable(float x, float y, float xs, float ys) : xCoordinate(x), yCoordinate(y), xSpeed(xs), ySpeed(ys) { } Drawable(const Drawable& s) : xCoordinate(s.xCoordinate), yCoordinate(s.yCoordinate), xSpeed(s.xSpeed), ySpeed(s.ySpeed) { } virtual ~Drawable() {} /* Pure Virtual Functions */ virtual void draw() = 0; virtual void update(Uint32 ticks) = 0; virtual void advanceFramesUp() = 0; virtual void advanceFramesDown() = 0; virtual void resetFrames() = 0; virtual void setFrames(std::vector<Frame> *) = 0; virtual void shoot() = 0; virtual bool shooting() const = 0; virtual bool collision(float, float) const = 0; virtual bool isExploding() const = 0; virtual void cullBullets() = 0; /* Non Virtual Functions */ float getX() const { return xCoordinate; } float getY() const { return yCoordinate; } void setX(float x) { xCoordinate = x; } void setY(float y) { yCoordinate = y; } float getSpeedX() const { return xSpeed; } float getSpeedY() const { return ySpeed; } void setSpeedY(float s) { ySpeed = s; } void setSpeedX(float s) { xSpeed = s; } void incrSpeedX(float incr) { xSpeed += incr; } void incrSpeedY(float incr) { ySpeed += incr; } void decrSpeedX(float incr) { xSpeed -= incr; } void decrSpeedY(float incr) { ySpeed -= incr; } void dragSpeedX(float incr) { xSpeed *= incr; } void dragSpeedY(float incr) { ySpeed *= incr; } protected: float xCoordinate; float yCoordinate; float xSpeed; float ySpeed; }; #endif
Duck is a derived class of Drawable. It has a few other private variables, including a vector of type Frame (Another derived of drawable, different hierarchy), a vector of type bullet (A derived of sprite, sprite derived from Drawable), and a couple other primitive data types. It also has all the pure-virtual functions from Drawable defined. Here's the code:
C++ Syntax (Toggle Plain Text)
#include <vector> #include <iostream> #include "frame.h" #include "drawable.h" #include "bullet.h" using std::vector; class Duck : public Drawable { public: //Default Constructor Duck(float x, float y, float xs, float ys, Frame *f, int i) : Drawable(x, y, xs, ys), currentFrame(0), bulletFrame(f), shootDirection(i){ //Destructor ~Duck() { } /* Inline Functions */ //getFrame function. Returns member variable Frame frame Frame* getFrame() const { return new Frame((*duckFrames)[currentFrame % duckFrames->size()]); } //setFrames function. Sets duckFrames to passed frame vector pointer void setFrames(std::vector<Frame> *f) { duckFrames = f; } //getCurrentFrame function. Returns the index of the current frame int getCurrentFrame() const { return currentFrame % duckFrames->size(); } //isExploding: Returns false, Duck objects cannot be exploding and ducks bool isExploding() const { return false; } //shooting function. Returns true if bullets vector is non-empty bool shooting() const { return bullets.size() > 0; }//(bullets.size() > 0); } //resetFrames function. Resets currentFrame to 0 void resetFrames() { currentFrame = 0; } /* Stub Defined Virtual Functions */ void advanceFramesUp() {} void advanceFramesDown() {} /* Implementation Defined Functions */ //Shooting and collision functions void cullBullets(); void shoot(); float distance(float x1, float y1, float x2, float y2) const; bool collision(float x, float y) const; //Drawing Functions void advanceFrame(Uint32 ticks); void update(Uint32 ticks); void draw(); private: //Vector for duck frames of animation std::vector<Frame> *duckFrames; //Vector for current Frame of animation int currentFrame; //Frame pointer for bullet image Frame *bulletFrame; //Vector of bullets vector<Bullet> bullets; int shootDirection; }; //IMPLEMENTATION OF DUCK.H #include "duck.h" //Draw Function: //Draws player to screen, draws players active bullets void Duck::draw() { } void Duck::advanceFrame(Uint32 ticks) { } //Update function //updates the duck's location along with the location of all active duck-bullets void Duck::update(Uint32 ticks) { } //cullBullets function //Erases bullets that have traveled too far void Duck::cullBullets() { } //Shoot function //Creates new bullets in the player::std::<Bullet>Vector void Duck::shoot() { } //Collision function //Checks for collisions between duck-bullets and a set of x,y coordinates bool Duck::collision(float x, float y) const { } //Distance function //Finds the hypot distance between two sets of points float Duck::distance(float x1, float y1, float x2, float y2) const { }
Finally, SmartDuck is a derived class of Duck. It only overloads the Update and Draw functions, inheriting everything else, as is. It has a reference to another class (Player, so it can get data access), along with an enumerator, and another primitive in its private section. There are a couple things commented out in the header, those are purely for debugging purposes.
C++ Syntax (Toggle Plain Text)
#include <iostream> #include "duck.h" #include "player.h" class SmartDuck : public Duck { public: SmartDuck(float x, float y, float xs, float ys, Frame *f, Drawable &p, /* SDL_Surface *screen ,*/ int i) : Duck(x, y, xs, ys, f, i), /*io(IOSingleton::getInstance(screen))*/ player(p), currentMode(NORMAL), initSpeedX(xs) { } void draw(); void update(Uint32 ticks); enum MODE {NORMAL, TRAIL, PANIC}; private: //IOSingleton *io; Drawable & player; MODE currentMode; float initSpeedX; }; //IMPLEMENTATION FOR SMARTDUCK.H #include <cmath> #include "smartDuck.h" const float SAFE_DISTANCE = WIDTH / 2; const float MIN_DUCK_XSPEED = -300; const float MAX_DUCK_XSPEED = -200; float distance(int x1, int y1, int x2, int y2) { } void SmartDuck::draw() { } void SmartDuck::update(Uint32 ticks) { }
Finally (Sorry, this is getting a little absurd), we have the Player class, immediatly derived from Drawable.
C++ Syntax (Toggle Plain Text)
#include <vector> #include <iostream> #include "frame.h" #include "drawable.h" #include "bullet.h" using std::vector; class Player : public Drawable { public: //Default constructor Player(float x, float y, float xs, float ys, Frame *f) : Drawable(x, y, xs, ys), currentFrame(0), bulletFrame(f) {} //Destructor ~Player() { delete bulletFrame; } /* Implementation defined functions */ void draw(); bool collision(float x, float y) const; float distance(float x1, float y1, float x2, float y2) const; void cullBullets(); void shoot(); void advanceFramesUp(); void advanceFramesDown(); /* Inline functions */ //setFrames function. Sets the vector object playerFrames to vector pointer parameter void setFrames(std::vector<Frame> *f) { playerFrames = f; } //getFrame function. Returns the current frame object Frame* getFrame() const { return new Frame((*playerFrames)[currentFrame]); } //getCurrentFrame function. Returns the index of the current frame int getCurrentFrame() const { return currentFrame; } //shooting function. Returns true if there are bullets draw on the screen bool shooting() const { return(bullets.size() > 0); } //isExploding function. Returns false, as players are not exploding bool isExploding() const { return false; } //Update function. Updates the position of the player sprite void update(Uint32 ticks); //resetFrames function. Resets currentFrame to 0 void resetFrames() { currentFrame = 0; } private: std::vector<Frame> *playerFrames; int currentFrame; Frame *bulletFrame; vector<Bullet> bullets; }; //IMPLEMENTATION OF PLAYER.H #include "player.h" //Update function //updates the players location along with the location of all active player-bullets void Player::update(Uint32 ticks) { } //cullBullets function //Erases bullets that have traveled too far void Player::cullBullets() { } //Draw Function: //Draws player to screen, draws players active bullets void Player::draw() { } //advanceFramesUp function, advances frames for movement in up direction void Player::advanceFramesUp() { } //advanceFramesDown function, advances frames for movement in down direction void Player::advanceFramesDown() { } //Shoot function //Creates new bullets in the player::std::<Bullet>Vector void Player::shoot() { } //Distance function //Finds the hypot distance between two sets of points float Player::distance(float x1, float y1, float x2, float y2) const { } //Collision function //Checks for collisions between player-bullets and duck objects bool Player::collision(float x, float y) const { }
There errors I'm getting are:
•
•
•
•
gameManager.o: In function `Player':
/home/yates/Desktop/the abstract expirement/player.h:14: undefined reference to `vtable for Player'
gameManager.o: In function `GameManager::loadPlayer()':
/home/yates/Desktop/the abstract expirement/gameManager.cpp:302: undefined reference to `vtable for Player'
gameManager.o: In function `SmartDuck':
/home/yates/Desktop/the abstract expirement/smartDuck.h:9: undefined reference to `vtable for SmartDuck'
gameManager.o: In function `GameManager::loadDucks()':
/home/yates/Desktop/the abstract expirement/gameManager.cpp:199: undefined reference to `vtable for SmartDuck'
gameManager.o: In function `GameManager::fragDucks()':
/home/yates/Desktop/the abstract expirement/gameManager.cpp:226: undefined reference to `typeinfo for Player'
Nota Bene: the player object is Drawable*, the ducks object is std::vector<Duck*>
C++ Syntax (Toggle Plain Text)
void GameManager::loadPlayer() { player = new Player(50, HEIGHT / 2, 0, 0, new Frame(bulletSurface, screen, bulletSurface->w, bulletSurface->h, 0, 0)); player->setFrames(playerFrames); } void GameManager::loadDucks() { //Trivial code omitted Drawable pDuck pDuck = new SmartDuck(x, y, xs, ys, new Frame(missleSurface, screen, missleSurface->w, missleSurface->h, 0, 0), *player, /* screen ,*/ 1); pDuck->setFrames(duckFrames); ducks.push_back(pDuck); } void GameManager::fragDucks() { //Additional Code Omitted, line 225 if (dynamic_cast<Player*>(player)->collision(duckX, duckY)) //Additional Code omitted }
So it seems my errors are coming from Construction and trying to cast pointer objects. The obvious thought is, why not take out the cast in fragDucks? Well, unfortunately, I've introduced a fairly long polymorphic hierarchy (There are still 4 or so classes I haven't posted, but are working fine), and if I don't do the cast, I risk referencing a null pointer, or accessing a function not defined for the class player currently represents.
So I'm sorry this got so long, but you've been very helpful so far, and I appreciate any further time you put into looking at my code. Hopefully it doesn't make your eyes bleed too badly.
•
•
Join Date: Nov 2008
Posts: 397
Reputation:
Solved Threads: 72
Sorry I had a quick look at this. The problem is that I cant compile it since there is lots missing and you have a link-time error.
Additionally you have missed (I think) a "}" on the duck constructor.
Can you post the program as a tar.gz or however you like, but put it as an attachment. (sorry I should have said that in the first message)
Additionally you have missed (I think) a "}" on the duck constructor.
Can you post the program as a tar.gz or however you like, but put it as an attachment. (sorry I should have said that in the first message)
•
•
Join Date: Nov 2008
Posts: 4
Reputation:
Solved Threads: 0
Thanks for the look, perhaps I should've asked about posting it in the first place. The missing brace is most likely a typo in the code that I had to modify before posting. But anyway...
Here it is. It's in .zip form because apparently Daniweb doesn't like .tar.gz. I've made a few little adjustments to it to help size and complexity, like disabling a couple in-program debugging features, sound, etc. But a heads up, that caused a number of unused parameter/unused variable warnings, but it shouldn't really have any effect on the heart of the problem.
It's C++ / SDL, but the necessary SDL libraries are not included. They're kind of weighty, and one of them (Vanilla SDL) is OS specific. They can easily be downloaded via Dev-Cpps Packaging system, or the Synaptic Package Manager in Linux. Below are links to download them from the official SDL website, where they can be downloaded in compressed form.
SDL
http://libsdl.org/download-1.2.php
SDL_Image
http://www.libsdl.org/projects/SDL_image/
SDL_TTF
http://www.libsdl.org/projects/SDL_ttf/
SDL_Mixer
http://www.libsdl.org/projects/SDL_mixer/
Thanks again for your help,
Yates Monteith
Here it is. It's in .zip form because apparently Daniweb doesn't like .tar.gz. I've made a few little adjustments to it to help size and complexity, like disabling a couple in-program debugging features, sound, etc. But a heads up, that caused a number of unused parameter/unused variable warnings, but it shouldn't really have any effect on the heart of the problem.
It's C++ / SDL, but the necessary SDL libraries are not included. They're kind of weighty, and one of them (Vanilla SDL) is OS specific. They can easily be downloaded via Dev-Cpps Packaging system, or the Synaptic Package Manager in Linux. Below are links to download them from the official SDL website, where they can be downloaded in compressed form.
SDL
http://libsdl.org/download-1.2.php
SDL_Image
http://www.libsdl.org/projects/SDL_image/
SDL_TTF
http://www.libsdl.org/projects/SDL_ttf/
SDL_Mixer
http://www.libsdl.org/projects/SDL_mixer/
Thanks again for your help,
Yates Monteith
•
•
Join Date: Nov 2008
Posts: 397
Reputation:
Solved Threads: 72
Oh I am sorry but I have just LOL big time!!!
You forgot to compile and include smartDuck.cpp and player.cpp in you makefile.
Well in light of that I would suggest that your next project look at splitting the program into shared libraries built in sub-directories and using some Makefile builder.
For this project, just add a player.o and smartDuck.o to your makefile and remember to add it to the link line.
p.s. Debugging with the -O2 option is pretty hairy, I would drop that from your makefile [Except production release, but then you drop the -g]
Sorry to put you through the trouble of sending a whole project file.
You forgot to compile and include smartDuck.cpp and player.cpp in you makefile.
Well in light of that I would suggest that your next project look at splitting the program into shared libraries built in sub-directories and using some Makefile builder.
For this project, just add a player.o and smartDuck.o to your makefile and remember to add it to the link line.
p.s. Debugging with the -O2 option is pretty hairy, I would drop that from your makefile [Except production release, but then you drop the -g]
Sorry to put you through the trouble of sending a whole project file.
![]() |
Similar Threads
- Undefined reference to 'vtable for ...' (C++)
- Polymorphism Question (C++)
- Problem compiling (C++)
- gcc on windows-linking problem (C++)
- Program Crashing PT2 (C++)
Other Threads in the C++ Forum
- Previous Thread: How to read strings into 1D array and more?
- Next Thread: Function not calling a variable
Views: 493 | Replies: 6
| Thread Tools | Search this Thread |
Tag cloud for C++
6 add api array arrays beginner binary bitmap c++ c/c++ calculator char class classes code compile compiler console conversion convert count data delete desktop directshow dll encryption error file forms fstream function functions game getline givemetehcodez google graph homeworkhelper iamthwee ifstream input int integer java lazy lib linkedlist linux loop looping loops map math matrix memory microsoft newbie news node number output parameter pointer problem program programming project proxy python random read recursion recursive reference return sort string strings struct studio system template templates test text tree unix url variable vector video visual visualstudio win32 windows winsock word wordfrequency wxwidgets





