【问题标题】:C++ : Clearing nested vectors leads to strange resultC++:清除嵌套向量会导致奇怪的结果
【发布时间】:2018-06-28 22:57:52
【问题描述】:

我试图 clear() 一个嵌套向量,但该向量没有被清除,而是填满了我计算机的所有内存。 这是重现该行为的代码:

#include <iostream>
#include <vector>

using namespace std;

main(int argc, char* argv[]){   
    int d, j;
    int D = 2;
    vector<int> N = {2,2};  
    vector<vector<vector<int>>> v;

    v.resize(D);
    for(d = 0; d < D; d++)
            v[d].resize(N[d]);

    v.clear();
    for(d = 0; d < D; d++)
        for(j = 0; j < N[d]; j++)
            cout << "d : " << d << ", j : " << j << ", v[d][j].size() : " << v[d][j].size() << endl;
}

我在 x86_64-linux-gnu 上使用 gcc 版本 5.4.1 并使用

进行编译
g++ -std=c++17 freeing_vector.cpp && ./a.out

其中 freeing_vector.cpp 是我之前给出的代码。 输出如下:

d : 0, j : 0, v[d][j].size() : 0
d : 0, j : 1, v[d][j].size() : 0
d : 1, j : 0, v[d][j].size() : 18446744073707429092
d : 1, j : 1, v[d][j].size() : 0

现在有趣的部分是:请确认删除 v.clear() 会产生预期的结果。 然后尝试用D不同的数字改变N的内容,比如

N = {3, 4};

在我的电脑上不会出错。一般来说,无论 D 是什么,在我看来,如果 N 包含至少两个等于元素,就会发生这种奇怪的行为。 所以两个问题: 您是否在计算机上观察到相同的行为? 你明白为什么吗?

【问题讨论】:

  • v[0] 是向量为空时未定义的行为。之后的一切都是无关紧要的。
  • 您发现未定义的行为很难推理。 UB 可以做任何事情,最令人头疼的 UB 是代码似乎可以完美运行,直到您最大的客户在他们最重要的生产日午夜崩溃。这就是存在静态和动态代码分析工具的原因

标签: c++ vector


【解决方案1】:

std::vector::clear 将破坏所有元素:

从容器中移除所有元素。

使任何引用包含元素的引用、指针或迭代器无效。任何过去的迭代器也会失效。

您不能访问超过向量末尾的数据并期望任何正常的事情发生。这显然是UB。

访问未分配的数据可能会导致返回 0。但是,无法保证代码显示 UB 时会发生什么。推理如何以不同方式访问数据会产生不同的结果是没有用的,它完全是不确定的。

尝试使用边界检查代码迭代向量,例如:

std::vector<std::vector<std::vector<int>>> v(2, std::vector<std::vector<int>>(2, std::vector<int>{}));
//v.clear();
for (auto&& v1 : v) {
    for (auto&& v2 : v1) {
        std::cout << v2.size() << std::endl;
    }
}

现在,取消注释 clear() 语句,看看你得到了多少打印输出。

【讨论】:

    【解决方案2】:

    您清除向量,然后尝试使用索引对其进行迭代。你期望会发生什么?尝试使用v.at(x) 代替v[x] 看看会发生什么

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 2012-10-29
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多