【问题标题】:c++ Segmentation fault with list iterator带有列表迭代器的c ++分段错误
【发布时间】:2015-10-29 23:03:17
【问题描述】:

我无法访问指向地图内列表的迭代器。 尽管网上描述了很多类似的问题,但我没有找到正确的解释。

我有一个包含“可见对象”的管理器对象;当它们是单个时,它们存储在地图中,当它们可以同名时,它们存储在地图内的列表中。我有一些功能必须浏览整个地图,并且在尝试访问列表迭代器时程序崩溃。

我会尽量只给你必要的,如果需要的话,要求更多。

Manager.h:

class VisibleObject;

class Manager
{
public:
    ~Manager ();

    bool addObject (std::string, VisibleObject*);
    bool addObjectToList (std::string, VisibleObject*);

    bool removeObject (std::string);
    bool removeObjectList (std::string);
    void clean ();

    VisibleObject* getObject (std::string);
    std::list<VisibleObject*>* getObjectList (std::string);

    void updateAll (float);
    void drawAll (sf::RenderWindow&);

private:
    std::map<std::string, VisibleObject*> m_objects;
    std::map<std::string, std::list<VisibleObject*>> m_objectLists;
};

在 Manager.cpp 中:

/// Add a single object
bool Manager::addObject (std::string p_name, VisibleObject* p_object)
{
    std::map<std::string, VisibleObject*>::iterator itr = m_objects.find(p_name);
    if (itr != m_objects.end())
        return false;
    m_objects.insert(std::pair<std::string, VisibleObject*> (p_name, p_object));
    return true;
}

/// Add an object to a list (create list if needed)
bool Manager::addObjectToList (std::string p_name, VisibleObject* p_object)
{
    std::map<std::string, std::list<VisibleObject*>>::iterator itr = m_objectLists.find(p_name);
    if (itr != m_objectLists.end())
    {
        itr->second.push_back(p_object);
        return true;
    } else
    {
        std::list<VisibleObject*> objectList;
        m_objectLists.insert(std::pair<std::string, std::list<VisibleObject*>> (p_name, objectList));
        m_objectLists[p_name].push_back(p_object);
        return false;
    }
}

/// This is where the problem occures
void Manager::drawAll (sf::RenderWindow& p_window)
{
    for (std::map<std::string, VisibleObject*>::iterator itr = m_objects.begin() ; itr != m_objects.end() ; itr++)
        (*itr).second->draw(p_window); // Seems to work fine
    for (std::map<std::string, std::list<VisibleObject*>>::iterator mapItr = m_objectLists.begin() ; mapItr != m_objectLists.end() ; mapItr++)
        for (std::list<VisibleObject*>::iterator listItr = (*mapItr).second.begin() ; listItr != (*mapItr).second.end() ; listItr++)
            (*listItr)->draw(p_window); // This is when I get a segmentation fault while debugging (signal SIGSEGV)
}

崩溃时应该已经有 2 个单个对象和许多列出的对象。

我没有更改构造函数,因为它看起来不需要初始化某些东西(唯一的问题是访问列表时)。 VisibleObject::draw(...) 是虚拟的。

EDIT : manager 是静态类 Game 的一个属性。这是我可以从任何类和添加一些对象的函数中获取管理器的部分:

Manager& Game::getManager ()
{
    return m_manager;
}

void Game::start ()
{
    Grid *grid = new Grid();
    m_manager.addObject("GRID", grid);
    Tetrimino *tetrimino = new Tetrimino();
    m_manager.addObject("TETRIMINO", tetrimino);
    /* ... */
}

我在对象 Grid 的构造函数中添加了 Visible Objects。我认为它不需要更多解释:

Grid::Grid ()
{
    VisibleObject::load("ressources/grid.png");
    Square *square = NULL;
    m_gridWidth = Game::getSettings().getInt("GRIDWIDTH");
    m_gridHeight = Game::getSettings().getInt("GRIDHEIGHT");
    m_squares.assign(m_gridWidth*m_gridHeight, square);
    Manager &manager = Game::getManager();
    for (int i=0 ; i<m_gridWidth*m_gridHeight ; i++)
        manager.addObjectToList("SQUARE", square);
}

Manager 的析构函数应该删除所有对象(但这与问题无关,是吗?)

【问题讨论】:

  • 请显示您将对象添加到管理器的代码。这很可能就是问题所在。
  • 从您发布的内容来看,我没有看到错误,甚至没有提示应该查看的其他内容。通常你可以使用调试器来获得更多关于段错误性质的线索,这样你就知道那个时候数据结构出了什么问题。
  • @NathanOliver 盲目猜测,我认为这个错误更有可能出现在对象被删除或应该被删除的地方,而不是它们被添加的地方。但这对我来说太盲目了,无法回复原来的问题,而且我认为你的猜测稍微有点盲目。
  • @JSF 那么没有提到任何关于删除对象的事情,我们知道他们正在添加它们,所以如果他们不能打印他们添加的东西,我不会表明这是一个盲目的猜测
  • 发布的片段几乎没有相关性。没有关于对象在哪里分配以及如何管理它们的生命周期的消息。您可能想使用std::shared_ptr。还有std::multimap.

标签: c++ list pointers iterator segmentation-fault


【解决方案1】:

当试图创建一个列表来添加对象时,这个列表在一个函数中被声明和删除(正如 R sahu 所建议的那样):这是错误代码:

std::list<VisibleObject*> objectList;
m_objectLists.insert(std::pair<std::string, std::list<VisibleObject*>> (p_name, objectList));
m_objectLists[p_name].push_back(p_object);

当到达“Manager::addObjectToList”函数的末尾时,这个列表被删除了,但仍然被经理指向。我用指针创建了它:

std::list<VisibleObject*>* objectList = new std::list<VisibleObject*>;
m_objectLists.insert(std::pair<std::string, std::list<VisibleObject*>> (p_name, *objectList));
m_objectLists[p_name].push_back(p_object);

编辑:当我将 Squares 添加到对象列表时还有一个问题:我用 nullptr 初始化 Squares,程序无法访问 Square 的函数。

【讨论】:

    【解决方案2】:

    问题很可能是由于悬空指针造成的。当VisibleObject 被删除时,我看不到任何更新Manager 列表的代码。分割线

    (*listItr)->draw(p_window);
    

    进入

    VisibleObject* object = *listIter;
    object->draw(p_window);
    

    然后,您可以判断问题是否与列表迭代器有关,我怀疑不是,或者问题是由悬空指针引起的。

    【讨论】:

    • 仍然存在分段错误。
    • @Zessirb,您在哪一行看到分段错误?
    • @R Sahu 程序第一次到达“(*listItr)->draw(p_window);”行
    • @Zessirb,试试这两行建议,看看问题是访问迭代器还是调用对象上的成员函数。我怀疑问题出在第二行。
    • 一开始没听懂,抱歉;它是第二行,“object->draw(p_window);”
    猜你喜欢
    • 1970-01-01
    • 2017-10-10
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2015-05-19
    相关资源
    最近更新 更多