带和不带初始化的向量分段故障 我在C++中做了一些向量实验。我使用的代码如下 #include <vector> #include <iostream> int main() { std::vector<float> aVector = std::vector<float>(10); // IMPORTANT LINE std::cout << "Vector size: " << aVector.size() << std::endl; aVector.clear(); aVector[0] = 2.2; std::cout << "Vector size: " << aVector.size() << std::endl; aVector.push_back(0.1); std::cout << "Vector size: " << aVector.size() << std::endl; aVector.clear(); std::cout << "Vector size: " << aVector.size() << std::endl; aVector[0] = 2.1; std::cout << "Vector size: " << aVector.size() << std::endl; return 0; } #包括 #包括 int main() { std::vector aVector=std::vector(10);//重要行 std::cout
自开始,带和不带初始化的向量分段故障 我在C++中做了一些向量实验。我使用的代码如下 #include <vector> #include <iostream> int main() { std::vector<float> aVector = std::vector<float>(10); // IMPORTANT LINE std::cout << "Vector size: " << aVector.size() << std::endl; aVector.clear(); aVector[0] = 2.2; std::cout << "Vector size: " << aVector.size() << std::endl; aVector.push_back(0.1); std::cout << "Vector size: " << aVector.size() << std::endl; aVector.clear(); std::cout << "Vector size: " << aVector.size() << std::endl; aVector[0] = 2.1; std::cout << "Vector size: " << aVector.size() << std::endl; return 0; } #包括 #包括 int main() { std::vector aVector=std::vector(10);//重要行 std::cout,c++,stdvector,C++,Stdvector,自开始,clear()使指向std::vector对象的任何元素的所有内容(引用、指针…)无效,但不会释放内存,因为capacity()保持不变。向量分配的内存不限于向量使用的内存。让我们一步一步地浏览程序。请注意,我将描述实际发生的情况;在aVector.size()尝试写入aVector[0]时,正式调用未定义的行为==0无论您最初是否分配了任何元素): 容量告诉您已分配了多少个单元 顺便说一句,您可以编写std::vector(10); 现在你知道了 std::cout <<
clear()
使指向std::vector
对象的任何元素的所有内容(引用、指针…)无效,但不会释放内存,因为capacity()
保持不变。向量分配的内存不限于向量使用的内存。让我们一步一步地浏览程序。请注意,我将描述实际发生的情况;在aVector.size()尝试写入aVector[0]
时,正式调用未定义的行为==0
无论您最初是否分配了任何元素):
容量告诉您已分配了多少个单元
顺便说一句,您可以编写std::vector(10);
现在你知道了
std::cout << "Vector size: " << aVector.size() << std::endl;
这会将end
重置为等于begin
并销毁新端点以外的所有对象(对于float
而言,这通常意味着什么都不做;但是调试版本可能会用NaN覆盖浮动)。也就是说,向量现在看起来如下所示:
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
| \----------------------------------------------------\
| |
V V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
|/-----/
|
V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
| //
| |
V V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0.1 | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
你看,记忆还在那里
aVector[0] = 2.2;
由于std::vector::operator[]
不执行范围检查(尽管调试版本可能会执行这些检查),这将导致分配begin
指向的浮点值。因为即使当前未初始化,也可以分配浮点值(如果使用std::vector
,情况会有所不同),此任务成功,您现在有
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
|/-----/
|
V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 2.2 | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
其次,
成员push_back
将首先检查end
之后是否有另一个元素的空间(在本例中显然有),如果没有,则重新分配(现在不适用),然后只需在*end
处构造一个该值的新对象并递增end
。因此,现在的向量如下所示:
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
| \----------------------------------------------------\
| |
V V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
|/-----/
|
V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
| //
| |
V V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0.1 | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
如您所见,对于向量,您的2.2
实际上不存在,因此它被新构造的0.1
覆盖
由于程序的其余部分只是重复前面的步骤(结果相同),我就到此为止
现在,如果一开始您没有请求任何元素,向量最初不会分配内存,因此尝试写入
aVector[0]
将导致分段错误。是的,这是我在(此链接)中发现的。[由某个人在问题的评论中发布(但评论已被删除)。它说的正是您所指出的。当向量没有元素时(无论当时是否有容量),编写aVector[0]
是一种未定义的行为,更不用说在没有初始化的情况下声明向量会将其容量设置为0,最终导致seg错误。非常详细的回答,顺便说一句。“将导致分段错误”不,您观察到,在您的平台上,当时.UB是U。它可能会践踏不相关的数据
+-------+-----+-------------+
| begin | end | capacity=10 |
+-------+-----+-------------+
| |
| //
| |
V V
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0.1 | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? | ??? |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+