未初始化的内存块上的向量分配和类似问题

时间:2010-03-02 13:05:25

标签: c++ memory memory-management vector variable-assignment

例如,

vector<vector<string> > test g ++,你可以做到

test.reserve(10);
test[0] = othervector;
test[9] = othervector;

它没有崩溃。理论上说你不应该这样做,因为你要将一个向量分配给认为它是一个向量的一块内存。
但它就像下一个一样:

#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main(){
    vector<string> first_vector;
    vector<string> &second_vector = *(vector<string>*)new char[sizeof(vector<string>)];
    first_vector.push_back("whatever");
    first_vector.push_back("whatever2");
    first_vector.push_back("whatever3");
    second_vector = first_vector;
    cout << "0 " << second_vector[0] << " \n";
    cout << "1 " << second_vector[1] << " \n";
    cout << "2 " << second_vector[2] << " \n";
}

这让我觉得向量的赋值运算符实际上复制了所有,或者至少足够的向量实现的字段,以便在未初始化的情况下呈现完全有效的向量。

嗯,这对我来说显然是未定义的行为,唯一的问题是它按预期工作,我在目前正在检查的代码库中发现了很多这些。

在其他容器中是否还有更多像这样的案例?从来没有见过一个看起来如此容易犯错误的人,但即使你犯了错误,它确实有效。

编辑:这不是关于如何正确地执行上述操作或抱怨编译器行为,它试图找到容易发生的类似问题,并且很难在以后发现,就像这一个。< / p>

4 个答案:

答案 0 :(得分:2)

所以你要求任意滥用STL?

我认为一个相当典型的可以让初学者怀疑库中的错误是试图存储没有在容器中正确复制的对象。我想这可能会或可能不会起作用。

另一个常见错误是没有考虑迭代器失效(例如在循环时插入/擦除)。

使用无效的演员表可能会创建各种场景。

答案 1 :(得分:2)

“在其他容器中是否还有更多像这样的情况?”

吨。而且我不是在开玩笑。我可以提出数以千计的标准。

例如,如果传入两个不相关的迭代器,几乎所有采用迭代器范围的函数都会以令人讨厌的方式破坏。它们也可以默默地“工作”但是错误地,特别是如果你传入两个向量迭代器。

同样,在我所知道的所有实现中,对于任何类型,T reinterpret_cast<T&>(&random_bytes).operator=(T());可能适用于random_bytes的某些值。它仍然是UB。

答案 2 :(得分:0)

“未定义的行为”就是:undefined。您在一个操作系统下的一个编译器上发现了一种情况,其行为符合您的预期。这实际上很常见 - 编译器不会将“未定义的行为”称为“自动段错误”!但是未定义行为的问题在于,因为标准不保证它,如果您以后更改操作系统,编译器或升级到同一编译器的更高版本,则不能依赖于保持相同的行为。它可能会在你的脸上爆炸。

答案 3 :(得分:-1)

你应该使用vector :: resize而不是vector :: reserve。

我也犯了一次这个错误,它在32位Windows上没有问题,但是当所有内容都被编译为64位时崩溃了。

这就是'未定义'意味着:它可能有效,或者它可能会突然停止工作。不保证(甚至不保证它崩溃)。