【问题标题】:C++ - Object is destroyed before the destructor is executedC ++ - 在执行析构函数之前销毁对象
【发布时间】:2014-05-12 22:05:11
【问题描述】:

我有一个类,它有一个指向动态分配实例 (wallGameObjects) 的指针的 2D 向量,我想在调用析构函数时将其删除,但在析构函数执行时该向量已被销毁。

析构函数调用removeMaze():

MazeSceneBuilder::~MazeSceneBuilder()
{
    removeMaze();

    mSceneManager->destroySceneNode(mazeNode);
}

而且对象的成员变量已经没有了:

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();
}

“mGameObjectManager->removeGameObject(groundGameObject);”行上的断点显示这个:

this    0x00000000 <NULL>   MazeSceneBuilder *

这对我来说没有意义。我试图在对象被销毁之前调用“removeMaze()”,它工作得很好。 对象的成员是否应该在析构函数执行之前消失?

编辑:

根据要求,这是 MultiplayerMaze 的析构函数:

MultiplayerMaze::~MultiplayerMaze()
{
    destroyPhysicsWorld();
}

摧毁物理世界:

void MultiplayerMaze::destroyPhysicsWorld()
{
    delete dynamicsWorld;
    delete solver;
    delete collisionConfiguration;
    delete dispatcher;
    delete broadphase;
}

编辑 2:

MultiplayerMaze 类定义:

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 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();
};

【问题讨论】:

  • 你能看一下调用堆栈并检查你的析构函数在哪里被调用,如果它没有在你调用构造函数的那一行之后被自动调用?这 可以 为 nullptr,但前提是您手动调用构造函数在一个为 nullptr 的指针上。
  • 您可以在 a) C++ 语言实现缺陷、b) 宇宙射线粒子翻转 RAM 位、c) 您的代码破坏堆之间做出选择。 a 和 b 更容易消除。
  • @Muepe 在析构函数之后调用它: Multiplayer Maze.exe!MazeSceneBuilder::removeMaze() Line 192 C++ Multiplayer Maze.exe!MazeSceneBuilder::~MazeSceneBuilder() Line 30 C++ 我不知道从其他任何地方调用它,为什么?
  • @yoni0505 不是从哪里调用 removeMaze 而是从哪里调用你的构造函数?您是手动删除您的对象,还是从超出范围的对象中自动析构函数?
  • @yoni0505 - 但您没有禁用复制。因此,如果复制了 MazeSceneBuilder 对象,您的程序将表现出未定义的行为。但说真的,我们需要有一个正在运行的程序来查看您是如何使用这些类的。所有这些指针和成员都有太多可能出错的地方。也许重新编写代码以使用智能指针而不是赤裸裸的原始指针会很有帮助,如果不能消除您现在遇到的问题。

标签: c++ destructor


【解决方案1】:

这可能与析构函数无关,但请看一下:

// 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]);
        }
    }
}

你使用了两次mazeWidth。你不应该使用mazeHeight吗?如果迷宫不是方形的,您最终可能会在wallGameObjects 中使用一些未初始化的指针,这会产生不可预见的副作用,尤其是当这些对象具有破坏其他对象的析构函数时,等等。

由于类很复杂,我建议尽可能使用std::unique_ptr&lt;T&gt; 来模拟所有权。它将帮助您跟踪错误。

【讨论】:

  • 感谢您指出这一点,但问题仍然是所有成员变量(包括 mazeWidth 和 mazeHeight)都已发布。所以这个错误是无关的。
  • 使用空值this 调用MazeSceneBuilder 的析构函数的唯一方法是跳过delete 所做的空值检查。现在我推测:如果MazeSceneBuilder 在堆栈上或者是另一个类的成员,例如MultiplayerMaze,这可能是可能的。它的生命周期是什么?你如何删除MultiplayerMazeBaseApplication 里面有什么?
猜你喜欢
  • 1970-01-01
  • 2018-01-02
  • 2018-05-02
  • 2014-09-24
  • 2020-10-24
  • 1970-01-01
  • 2018-11-24
  • 2021-06-30
  • 2011-05-24
相关资源
最近更新 更多