Reputation: 359
I have a class which have a 2D vector of pointers to dynamically allocated instances (wallGameObjects) which I want to delete when the destructor is called, but by the time the destructor executes the vector is already destroyed.
The destructor calls removeMaze():
MazeSceneBuilder::~MazeSceneBuilder()
{
removeMaze();
mSceneManager->destroySceneNode(mazeNode);
}
And the object's member variables are already gone:
void MazeSceneBuilder::removeMaze()
{
// Remove walls
for (unsigned int x = 0; x < mazeWidth; x++)
{
for (unsigned int z = 0; z < mazeWidth; z++)
{
if (wallGameObjects[x][z] != nullptr)
{
mGameObjectManager->removeGameObject(wallGameObjects[x][z]);
}
}
}
// remove ground
mGameObjectManager->removeGameObject(groundGameObject);
// Destroy collision shapes
destroyCollisionShapes();
}
Breakpoint on the line "mGameObjectManager->removeGameObject(groundGameObject);" shows this:
this 0x00000000 <NULL> MazeSceneBuilder *
It doesn't make sense to me. I tried to call "removeMaze()" before the object is destroyed and it worked just fine. Are the object's members suppose to be gone before the destructor executes?
EDIT:
As requested, here's the destructor of MultiplayerMaze:
MultiplayerMaze::~MultiplayerMaze()
{
destroyPhysicsWorld();
}
destroyPhysicsWorld:
void MultiplayerMaze::destroyPhysicsWorld()
{
delete dynamicsWorld;
delete solver;
delete collisionConfiguration;
delete dispatcher;
delete broadphase;
}
EDIT 2:
MultiplayerMaze class definition:
class MultiplayerMaze : public BaseApplication
{
public:
MultiplayerMaze();
virtual ~MultiplayerMaze();
protected:
virtual void createScene();
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
virtual bool configure();
virtual void createPhysicsWorld();
virtual void destroyPhysicsWorld();
// Physics members
btBroadphaseInterface* broadphase;
btDefaultCollisionConfiguration* collisionConfiguration;
btCollisionDispatcher* dispatcher;
btSequentialImpulseConstraintSolver* solver;
btDiscreteDynamicsWorld* dynamicsWorld;
GameObjectManager gameObjectManager;
MazeSceneBuilder mazeSceneBuilder;
MazeGenerator mazeGenerator;
};
MazeSceneBuilder class definition:
class MazeSceneBuilder
{
protected:
std::vector<std::vector<bool>> mMaze;
unsigned int mazeWidth, mazeHeight;
float mMazeScale;
GameObjectManager* mGameObjectManager;
Ogre::SceneManager* mSceneManager;
Ogre::String mWallEntity;
Ogre::String mGroundMaterial;
Ogre::Entity* mGround;
Ogre::SceneNode* mazeNode;
btCollisionShape* wallCollisionShape;
btCollisionShape* collisionPlanes[5];
GameObject* groundGameObject;
std::vector<std::vector<GameObject*>> wallGameObjects;
void setupGround(); // Creates a plane entity using the ground materiala and the maze size.
void createCollisionShapes(); // Create collision shapes for the wall, ground, and bounding planes.
void destroyCollisionShapes();
void DestroyAllAttachedMovableObjects(Ogre::SceneNode* sceneNode);
public:
MazeSceneBuilder();
MazeSceneBuilder(GameObjectManager* gameObjectManager);
~MazeSceneBuilder();
void setGameObjectManager(GameObjectManager* gameObjectManager);
bool setMaze(std::vector<std::vector<bool>> maze); // Returns false if the provided maze was invalid.
void setMazeScale(float scale);
void setWallEntity(Ogre::String entityName); // Must be a square cuboid of 1x2x1
void setGroundMaterial(Ogre::String materialName); // Should be a tiled square texture.
void buildMaze();
void updateMaze(const std::vector<std::vector<bool>>& maze);
void removeMaze();
};
Upvotes: 1
Views: 563
Reputation: 519
This is probably not related to the destructor, but please have a look at:
// Remove walls
for (unsigned int x = 0; x < mazeWidth; x++)
{
for (unsigned int z = 0; z < mazeWidth; z++)
{
if (wallGameObjects[x][z] != nullptr)
{
mGameObjectManager->removeGameObject(wallGameObjects[x][z]);
}
}
}
You use mazeWidth
twice. Shouldn't you use mazeHeight
? If mazes are not square, you may end up using some uninitialized pointer in wallGameObjects
, with unforeseeable side effects, especially if those objects have a destructor that destroys other objects, and so on.
As the classes are complex, I suggest using std::unique_ptr<T>
when possible to model ownership. It will help you tracking the bug.
Upvotes: 1