断言失败:列出迭代器不可递增(不在循环中)

时间:2017-06-09 10:23:44

标签: c++ list iterator erase assertion

首先,早上好/白天/晚上,感谢任何花时间阅读此内容的人。

设置:

在我的代码中,我有两个不同的类:ColObj和QuadNode(即'碰撞对象'和四叉树中的一个节点,用于检查对象的接近程度。我知道有可能存在库,但是我需要编写自己的系统,所以它们在这里没用。)事情是这样的:当创建一个ColObj对象时,它被添加到一个合适的QuadNode中(该节点有一个std ::指向ColObj的指针列表),这样节点就可以在它与某些东西碰撞时通知它; ColObj对象还接收一个指向持有它的节点的指针和一个包含其地址的列表迭代器的列表迭代器,因此当它离开节点的边界或被销毁时,它可以“离开”它,并清理节点,即,从节点中删除并引用自身。我是这样做的,因为在很多情况下它会经常运行,我希望它能在不变的时间内完成。

守则:

这是用于将ColObj“附加”到QuadNode的方法。我怀疑问题不在这里。

void QuadNode::obj_add(ColObj *obj) {

    std::cout<<"QuadNode at depth ("<<depth<<") received new ColObj.\n";

    objects.push_back(obj);

    obj->holder  = this;
    obj->my_iter = std::prev( objects.end() );

    if ((int)objects.size() > MAX_OBJECTS && depth < MAX_DEPTH) split();

    }

这是ColObj用于清理节点的QuadNode方法。这是出于某种原因出现问题的地方。

void QuadNode::obj_list_erase(std::list<ColObj*>::iterator iter) {

    std::list<ColObj*>::iterator iter2 = objects.begin();

    objects.erase(iter);

    }

此方法的第一行只是为调试提供附加信息,之后将被删除。

错误:

最奇怪的是,在大多数情况下,代码工作正常。然后在某一点,随机地,它抛出一个断言失败,说“列表迭代器不可递增”。这是第一个奇怪的事情,我不是试图在我的代码中的任何地方增加它(虽然我知道std :: list :: erase会返回以下迭代器,但我从不尝试对无效或“过去 - ”进行此操作最后一个“迭代器”。

无论如何,Visual Studio提供启动调试器并在代码中放置一个断点,所以我很自然地同意。所以这是最奇怪的部分:

Local and auto variables, debugger screenshot

(因为我是新来的,所以不能嵌入图片,所以它就是这样)。

所以,除非我在这里严重错误,它告诉我传递的迭代器等于开始列表的迭代器,它的元素仍然存在于列表中并且对应于第一个(或者更确切地说是零) )列表的元素。然而,erase()方法失败了。 对于它的价值,我注意到程序每次破坏时,传递的迭代器都指向列表的第零个元素,尽管我可以确认即使列表中只有一个元素,该方法通常也能正常工作。

其他信息和结论:

我不是在代码中的任何其他地方手动递增迭代器(无论如何都非常小而且简单。)

我使用的IDE是Visual Studio Community 2015,但我不知道编译器版本。 (微软及其命名方案......)

我尝试在SO上找到关于这个的另一个帖子,但是我检查的每一个都是错误地将i ++放在列表迭代中,所以很抱歉,如果这是一个重复的线程。

我完全被这个问题搞糊涂了,因为通常在优秀的调试器,std :: cout和浏览之间我以某种方式修复了这个问题,但这次没有什么用处,所以任何建议或建议都会非常欢迎。

修改

有一件事我试过“只是因为”编辑QuadNode :: obj_list_erase方法,以便它将传递的迭代器与其列表的第一个迭代器(objects.begin())进行比较,如果它们相等则使用对象。 pop()删除它,否则擦除它。它不起作用,说迭代器不兼容,不管这意味着什么......

1 个答案:

答案 0 :(得分:0)

在发现我甚至无法将传递的迭代器与应该持有它的列表中的任何其他迭代器进行比较时(我得到断言失败:迭代器不兼容),我搜索SO以获取更多关于它意味着什么的信息,和...安德鲁卡什普尔是对的。我确实设法通过从列表中删除指向的元素并立即将其放回来但无需更新迭代器来使迭代器无效。

故事的道德:迭代器似乎指向“正确”的内存位置,它甚至可能指向与某些有效迭代器相同的地址,但这并不会使其有效或兼容。