2

每当我调用dominoes.erase()which 类型时,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 );
}

任何帮助将不胜感激。谢谢!

4

2 回答 2

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

如果它仍然存在段错误,则问题来自 class 的析构函数Domino。看看有没有什么腥味。您可以通过注释析构函数的部分(或全部)来进行快速测试,以了解问题出在哪里。调用erase将调用Domino.

如果没有实现析构函数,最好实现一个带有输出的析构函数(on cerr, not cout)以了解它是否到达那里或更早崩溃。是Domino派生类吗?它是否有任何其他对象或只有原始类型的组合?

编辑

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

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

不是它应该这样写的......我让你调试它作为练习。

至于为什么这是错误的根源:您说erasecrashed but not pop_back。两者之间的主要区别(实现差异,而不是明显的语义差异)是擦除导致所有元素在删除(使用=运算符)之后移动,因为std::vector需要连续存储元素。而 pop 只是改变了尾指针,并没有改变容器的其余部分。

于 2013-04-21T20:52:41.583 回答
0

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

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

此外,如果dominoes.size() == 0. 在这种情况下,您将擦除dominoes.end().

于 2013-04-21T20:54:02.710 回答