尝试push_back()时,矢量迭代器没有dereferencable错误

时间:2015-05-25 19:43:01

标签: c++ vector iterator stdvector dereference

当我的应用程序因VS的此错误消息崩溃时出现问题:“调试断言失败!(...)Expression:vector iterator not dereferencable”。

问题是,它在使用vector的push_back时发生。

这是代码。这是我的BigInt库,我决定将其作为练习来实现。这个bug隐藏在我的TestBigInt类中,我创建了(令人惊讶的)测试BigInt。这段代码确实很长,但我将这个漏洞缩小到了一小部分。 这是我给错误代码的输入:

/* "BigIntTestCases.txt": format { label num1 num2 autoChecked { } }
* { 1 3 2 1 { } }
* { 2 10 7 1 { } }
* { 3 21 9 1 { } }
* ...
*/
    int main() {
        ifstream ifs{ "BigIntTestCases.txt" };
        // read tests into vector<BigIntTest>
        for (auto it = tests.begin(); it != tests.end(); ++it) {
            std::cout << "Read: " << it->label << ' ' << it->num1 << ' ' << it->num2 << ' ' << it->autoChecked << '\n';
            performTest(ofs, (*it));
        }
    }

这给了我输出:

Read: 1 3 2 1
pushed_back exResults
pushed_back outResults
Read: 2 10 7 1
pushed_back exResults
CRASH

这是“TestBigInt.cpp”,这就是bug(在第一个函数的前4个push_backs中 - doTests()):

void TestBigInt::doTests()
{
    // fill outResults - vector of BigInt test results
    BigInt firstNum{ num1 };
    BigInt secNum{ num2 };

    outResult.push_back((firstNum + secNum).toString());
    outResult.push_back((secNum + firstNum).toString());
    outResult.push_back((firstNum - secNum).toString());
    outResult.push_back((secNum - firstNum).toString());
    outResult.push_back((firstNum * secNum).toString());
    outResult.push_back((secNum * firstNum).toString());
    std::cout << "pushed_back outResults\n";
}
void TestBigInt::autoFillExR()
{
    // fill vector exReults -- expected results
    int firstNum = stringToI(num1);
    int secNum = stringToI(num2);

    exResult.push_back(iToString(firstNum + secNum));
    // ... - essentialy the same as doTest()
    std::cout << "pushed_back exResults\n";
}
std::ostream& performTest(std::ostream& os, TestBigInt& t)
{   
    if (t.autoChecked) // if the results are to be autochecked, than fill the exResult -- else it is already full
        t.autoFillExR();

    t.doTests();

    for (auto itE = t.exResult.cbegin(), itO = t.outResult.cbegin(); itE != t.exResult.cend() && itO != t.outResult.cend(); ++itE, ++itO)
        if (*itE != *itO)
            os << "Test not passed: " << t.label  << ", " << distance(t.exResult.cbegin(), itE) << "\n\tExpected: " << *itE << ", got " << *itO << "\n";

    return os;
}

这是BigInt :: toString

的实现
std::string BigInt::toString() const
{
 // the digits are stored in "reversed order", i.e. digits[0] is the least significant digit
    std::string num;
    if (sign == Sign::negative)
        num += "-";
    for (auto it = digits.crbegin(); it != digits.crend(); ++it)
        num += ('0' + *it);
    return num;
}

我知道这是一个非常长的样本,但至少我把这个bug缩小了很多。坦率地说,我不知道为什么它不起作用。

非常感谢阅读这篇文章的任何人。如果你有任何关于它为什么会出错的想法,那么请把它贴在这里 - 我很无奈,并且会感激任何帮助

1 个答案:

答案 0 :(得分:0)

在推回时不能迭代向量,因为push_back可能使迭代器无效。

我无法在发布的代码(refer code)中看到上面提到的问题,因此我撤回了上面的答案。在查看所有代码之前,我已将其基于假设。

但是,鉴于此代码:

for (TestBigInt t; ifs >> t; )
        tests.push_back(t);

您是否意识到您始终在修改相同的t实例。您正在推送副本,但运营商&gt;&gt;总是修改原始实例,增加其向量。这是你想要的吗?您的结果数量超过6 ...