Home > Blockchain >  Vector out of boundaries access: why such behavior?
Vector out of boundaries access: why such behavior?

Time:03-22

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...

CodePudding user response:

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.

  • Related