在 "out of range of vector error" 中删除打印语句后输出不同的根本原因

Underlying reasons for different output after removing a print statement in an "out of range of vector error"

我有一个导致上述行为的最小代码:

vector<int> result(9); 
int count = 0;
cout << "test1\n"; // removing this line causes 'core dump'
for (int j=0; j < 12; j++)          
    result[count++] = 1;
cout << "test2\n";

result 是一个大小为 9 的向量,在 'for' 循环中我正在访问超出范围的元素。

现在,删除 test1 行,代码运行没有任何错误;但是有了这条 cout 行,我得到

* Error in `./out_of_range_vector2': free(): invalid next size (fast): 0x0000000001b27c20 *

我明白这是在告诉我 free() 遇到一些未分配给我的 malloc() 的内存,但是什么cout 行在这里扮演什么角色?我想多了解一下这里发生的事情。更具体地说,我有两个问题:

  1. 这是因为这两种情况下heap的不同状态造成的吗?如果是这样,究竟有什么不同?
  2. 为什么有时访问超出范围的元素不会出错?是不是因为没有超过vector的容量?

cout << "test1\n";

做很多事情,它可能会分配一个空闲内存。

写在向量边界之外是"undefined behavior",这与"getting an error"有很大不同。 "undefined behavior" 的意思是,谁编写了编译器和运行时库,可以随意忽略这些可能性以及发生的任何事情。他们可以这样做,因为程序员永远不会做那些事情,什么时候是 100% his/her 错误。在使用 operator[] 访问 std::vector 元素时防止、保护甚至简单地通知错误不是合同的一部分。

从技术上讲,可能发生的情况是写操作破坏了内存分配器使用的一些内部数据结构,这导致了之后的疯狂行为,这可能会也可能不会导致段错误。

段错误是当事情变得疯狂到甚至操作系统可以检测到程序没有做应该做的事情的时候,因为它请求访问甚至不存在的位置(所以肯定他们不能应该包含正在查找的数据的正确位置)。

然而,您可能会在未达到 "segfault" 点的情况下获得未定义的行为和损坏的数据,并且程序将简单地从错误的位置读取或写入不正确的数据,即使没有从正确的程序中获得任何可观察到的差异。这实际上是大多数时候发生的事情(不幸的是)。

那么当您使用未经检查的 opertor[] 读取或写入超出 std::vector 大小的内容时会发生什么?大多数时候什么都没有(显然)。然而,它可能会在那个错误之后为所欲为,包括在代码正确的地方表现得很疯狂,10 亿条机器指令之后,并且只有在这会造成严重损害的情况下。只是不要那样做。

使用 C++ 编程时,您绝对不会犯任何错误。没有"runtime error angels"像其他高级语言一样保护你。