调用vector.erase()时出现分段错误

时间:2013-04-21 20:29:00

标签: c++ std stdvector

每当我拨打dominoes.erase()类型std::vector<Domino>时,我都会遇到分段错误;即使我硬编码这个值。

一个单独的成员函数调用dominoes.push_back()来加载数据,我可以使用pop_back()从向量中删除并返回一个多米诺骨牌,所以我知道那里有数据。我有一个在Domino对象上创建的复制构造函数,并且工作得很好。我把它缩小到dominoes.erase()

Domino::Domino( const Domino &d ) {
    left = d.getHighPip();
    right = d.getLowPip();

}
Domino DominoCollection::drawDomino( void )
{

    int index = random.nextNumber( dominoes.size()  );
    Domino d( dominoes[index] );
    dominoes.erase( dominoes.begin() + index );

    return Domino( d );
}

非常感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:5)

尝试通过删除所有不必要的代码(对象复制,矢量访问...)来缩小错误范围。然后,如果问题确实来自erase,请添加警卫以确保索引正确。请尝试使用此代码:

#include <cassert>
void DominoCollection::drawDomino( void )
{
    assert(dominoes.size() != 0 && "Your vector is empty");
    int index = random.nextNumber( dominoes.size()  );
    assert(index < dominoes.size() && "Buffer overflow...");
    dominoes.erase( dominoes.begin() + index );
}

如果它仍然是段错误,则问题来自类Domino的析构函数。看看那里有什么可疑的东西。您可以通过注释析构函数的部分(或所有部分)来快速进行测试,以了解问题的来源。调用erase将调用Domino的析构函数。

如果没有实现析构函数,最好在其中实现一个输出(在cerr上,而不是cout),以确定它是否到达或早先崩溃。 Domino是派生类吗?它中是否有任何其他对象或仅包含原始类型的组合?

修改

我快速浏览了你的代码:问题来自赋值运算符:

Domino & Domino::operator = ( const Domino & d )
{
    *this = d;
}

这是 NOT 应如何编写...我让你调试它作为练习。

至于为什么这是bug的来源:你说erase崩溃但不是pop_back。两者之间的主要区别(实现差异,而不是明显的语义差异)是擦除导致所有元素在删除之后移位(使用=运算符),因为std::vector需要元素连续存储。而pop只是更改尾指针而不会改变容器的其余部分。

答案 1 :(得分:0)

根据您向我们展示的内容,int index的值似乎大于或等于dominoes.size()。否则,该代码可以正常工作。

我会检查random.NextNumber(dominoes.size())返回的内容。

此外,dominoes.size() == 0可能会出现此问题。在这种情况下,您将删除dominoes.end()