向量越界访问:为什么会有这样的行为?

Vector out of boundaries access: why such behavior?

我知道在 C++ 中使用 operator[] 越界访问 std::vector 会导致未定义的行为。所以,我不应该期望这样做有任何意义。但是,我很好奇幕后到底发生了什么。

考虑以下代码:

#include <iostream>
#include <vector>

int main() {
    {
        std::cerr << "Started\n";
        std::vector<int> v(2);
        std::cerr << "Successfully initialized vector\n";
        v[-1] = 10000;  // Note: if accessing v[3], nothing bad seems to happen
        std::cerr << "Successfully accessed element -1\n";
    }
    std::cerr << "Successfully destructed the vector\n";
}

使用 g++ (GCC) 11.2.0 在 GNU/Linux 上编译时,运行 此代码生成以下输出:

Started
Successfully initialized vector
Successfully accessed element -1
double free or corruption (out)
Aborted (core dumped)

为什么会发生这种情况?为什么会导致析构函数失败?为什么会产生这样的错误信息?

如果我使用某种结构将数组与它一起存储在堆栈中,我会理解它:然后我会不小心访问它位于 v[0] 之前的一些内部数据,并且可能会破坏某些东西.但据我所知,std::vector 的底层数组存储在堆上,所以我访问的数据甚至不应该属于它,不是吗?另外,因为我最后一次输出尝试是在退出块后立即进行的,其中只声明了向量,所以我看不到除了它的析构函数之外还有什么可以被调用,所以向量似乎在某种程度上受到了我的操作的影响。 .

一个可能发生的假设答案:UB 导致任意一块内存被覆盖。这称为内存损坏。

被覆盖的任意内存恰好在向量分配的动态内存之前。分配之前的任意一块内存恰好包含一个描述分配的“信息头”。调用析构函数时,会尝试释放内存。全局分配器检测到损坏的信息不一致,生成诊断消息并终止程序。

您系统上全局内存分配器的源代码可能如下所示:https://code.woboq.org/userspace/glibc/malloc/malloc.c.html#4326 link 专门指向产生错误消息的行。