矢量越界访问:为什么会出现这种行为?

发布于 2025-01-15 18:41:00 字数 1084 浏览 4 评论 0原文

我知道使用 operator[] 在 C++ 中对 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的底层数组存储在堆上,所以我访问的数据甚至不应该属于它,不是吗?另外,因为我的最后一次输出尝试是在退出仅声明了向量的块后立即进行的,所以我看不到除了它的析构函数之外还可以调用什么,所以向量似乎在某种程度上受到了我的操作的影响。 。

I am aware that out of boundary access of an std::vector in C++ with the operator[] results in undefined behavior. So, I should not expect anything meaningful doing that. However, I'm curious about what is actually happening there under the hood.

Consider the following piece of code:

#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";
}

When compiled on GNU/Linux with g++ (GCC) 11.2.0, running this code produces the following output:

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

Why could have that happened? Why does it cause the destructor to fail? Why does it produce such an error message?

I would understand it if I was using some structure that stored the array together with it on the stack: I would then accidentally access some of its internal data that lies right before v[0] and could have broken something. But as far as I know, the underlying array of std::vector is stored on heap, so the data that I access should not even belong to it, should it? Also, because my last output attempt is taken right after exiting the block with only vector declared in it, I don't see what else except for its destructor could have been called, so the vector seems to be somehow affected by my action...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

撕心裂肺的伤痛 2025-01-22 18:41:00

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

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

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

A hypothetical answer that could have happened: The UB caused arbitrary piece of memory to be overwritten. This is called memory corruption.

That overwritten arbitrary piece of memory happened to be right before the dynamic memory that the vector allocated. The arbitrary piece of memory right before the allocation happened to contain an "information header" that describes the allocation. When the destructor was called, there was an attempt to deallocate the memory. The global allocator detected that the corrupted information was inconsistent, produced the diagnostic message and terminated the program.

This is what the source code of the global memory allocator on your system may look like: https://code.woboq.org/userspace/glibc/malloc/malloc.c.html#4326 The link leads specifically to the line that produces the error message.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文