【问题标题】:Segfault when using std::set of pointers... can anyone explain this?使用 std::set of pointers 时出现段错误......谁能解释一下?
【发布时间】:2011-08-13 17:34:53
【问题描述】:

在我的游戏中,我创建了一个名为 Entity 的基类,我将其存储在一个集合中以供处理。我所有的游戏对象都派生自这个类,在我的初始化函数中将派生的指针类型添加到集合中没有问题。

问题在于从实体的Step() 函数中添加新元素。现在,在深入探讨之前,我将向您展示一些简化的代码:

class GameState
{
    public:
        GameState();
        ~GameState();
        ...
        set<Entity*> entities;
        void Add(Entity* e);
        void Remove(Entity* e);
    protected:
        set<Entity*> added, removed;
};

class Entity
{
    public:
        Entity();
        Entity(GameState* parent);
        virtual ~Entity();
        virtual void Step(const sf::Input& input);
        ...
        virtual void Destroy();
    protected:
        GameState* game;
};

GameState 中的 Add 和 Remove 函数只需将参数 e 分别添加到 addedremoved 集合中。在主循环中(GameState 中的其他地方),我在处理之前将元素从added 移动到entities,在处理之后我从entities 中删除来自removed 的元素。这确保了entities 在迭代期间不会被修改。

添加/删除功能非常简单:

void GameState::Add(Entity* e)
{
    added.insert(e);
}

void GameState::Remove(Entity* e)
{
    removed.insert(e);
}

每个派生实体都会在其构造函数中传递一个指向 GameState 的指针,并将其保存为 game。所以理论上从 Step 函数我应该能够通过像game-&gt;Remove(this); 这样的简单调用来添加和删除实体,但是我得到了一个段错误。经过一夜的谷歌搜索并且一无所获,我能够通过像这样实现Entity::Destroy() 来解决(部分)问题:

void Entity::Destroy()
{
    game->Remove(this);
}

所以我的第一个问题是:为什么this 在基类中而不在派生类中工作?

让我更困惑的是Add()。为什么Add(new Explosion(16,16,this)) 在 GameState 中可以工作,而game-&gt;Add(new Explosion(16,16,game)) 在我的对象中却不能工作?

我通过 gdb 运行它,它告诉我:

Program received signal SIGSEGV, Segmentation fault.
At c:/program files (x86)/codeblocks/mingw/bin/../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:482

引发错误的代码是:

_Link_type
  _M_begin()
  { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } //this line

总而言之,我不知道为什么我的指针会破坏 STL ......而且我有一种严重的感觉,我错过了一些非常基本的东西并导致所有这些头痛。谁能给我建议?

【问题讨论】:

  • 这么少的代码。使用std::set 时无代码。
  • 你如何保持主实体数组,一个你正在跨过的?
  • @Nawaz:我对其进行了编辑以显示 std::set 如何在辅助函数中使用。请注意,这些是我编写的堆栈跟踪中的最后几行。我传递给它们的指针应该是有效的,因为我只传递指向实体子类的指针,但由于某种原因它们不是。
  • @elevener 我使用 std::set 而不是数组
  • @aeron005 - 在这种情况下,你如何删除你的对象?

标签: c++ inheritance pointers segmentation-fault


【解决方案1】:

为什么Add(new Explosion(16,16,this))GameState 中工作但是 game-&gt;Add(new Explosion(16,16,game)) 在我的对象中不起作用?

如果是这种情况,那么唯一可能的解释是Entitygame 成员实际上并不指向GameState。检查它在构造时是否正确设置,并在使用前进行验证。

这与std::set 无关。问题是您使用的 std::set 是您通过损坏指针访问的类的一部分。

【讨论】:

  • 就是这样!所以现在我有一个快速的后续问题。在我的 Entity 构造函数中,我继续分配值“game = parent;”。在 Explosion 中,我这样调用父构造函数:“Explosion::Explosion(int xx, int yy, GameState* parent) : Entity(parent), frame(0)” 这样做会产生错误,但如果我把“游戏=父母;”有用。为什么我必须每次都分配它?当我调用它时,它不应该在基类构造函数中分配吗?
  • 如果Entity构造函数设置game,调用父构造函数只会设置game。你是在Entity::Entity(GameState* parent) 中设置game 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多