调试断言失败了visual studio 2015:矢量迭代器不是dereferencable

时间:2016-06-04 17:06:32

标签: c++ visual-studio-2015

我编写了一个简短的代码,使用while循环遍历(排序!)结构向量并根据其价格插入新元素(如果已经有特定价格的条目,新条目应该插入现有条目后面。

使用g++和Sublime Text 3一切正常(在本问题末尾输出),但使用Visual Studio 2015我收到错误:Debug Assertion Failed! ... Expression: vector iterator not dereferencable。 (请注意,如果新元素应附加在现有向量的末尾,则此错误仅会出现,如果我们将新元素更改为struc newEl = {5, 2.0},则VS和g++都可以正常工作。

代码如下所示:

#include <iostream>
#include <vector>

struct struc {
    int num;
    double price;
};

int main() {
    std::vector<struc> v = { { 1, 1.5 },{ 2, 1.6 },{ 3, 2 },{ 4, 2.6 } };
    struc newEl = { 5, 2.7 };

    std::vector<struc>::iterator it = v.begin();

    while (((*it).price <= newEl.price) && (it < v.end())) {
        it++;
    }

    v.insert(it, newEl);

    for (struc vec : v) {
        std::cout << vec.num << ", " << vec.price << std::endl;
    }

    std::cout << "Finished";
    return 0;
}

输出应该是(并且在g++和ST的情况下):

1, 1.5
2, 1.6
3, 2
4, 2.6
5, 2.7
Finished

现在我的问题是,导致VS中的错误的原因是什么?我需要更改它以使其在VS中工作?

非常感谢!

1 个答案:

答案 0 :(得分:6)

while (((*it).price <= newEl.price) && (it < v.end())) {

你需要检查你是否在结束之前取消引用迭代器并检查值:

while ( (it!=v.end()) && (it->price <= newEl.price)) {

否则你基本上保证你会取消引用end迭代器,这正是你想要避免的。

(你不能在大多数类型的迭代器上使用<,所以用!=检查循环是一种更常见的做法。)

您可能知道&&&#34;短路&#34;所以,如果第一个条件是false,那么第二个条件甚至不会被检查。这是由语言保证的(除非一些白痴超载operator&&,但幸运的是,这很少见,因为这是一个糟糕的主意)。这就是为什么我的版本是安全的。

现在,这个错误会触发Undefined Behaviour - 错误就在你身上!这种语言甚至不会帮助你,任何事情都可能发生。您的程序可能崩溃,它可能看起来正常工作,它可能每隔一段时间工作,或者它可以将您的笔记本电脑变成粉红色的长颈鹿。 C ++交易对你来说很快就会很快。

我知道Microsoft的实现,在调试模式下,checked iterators在这里抓住你的错误,代价是总是检查。在发布模式下,这不会发生。

我没有使用它,但根据this answer,GCC确实有类似的东西。

(顺便说一句,我真的认为使用std::endl是不好的做法。Here's why。有些人不同意我的意见。我想,了解它并做出自己的决定。 )