Search code examples
c++arraysruntime-errormemcpymemset

free(): invalid next size (fast): 0x0000000000f45160 ***


I've read about this error occurring due to freeing a non-allocated pointer (e.g. double-freeing a pointer) but in my case the offending line looks like this:

memset(data + prev_bytes, 0, sizeof(int) * size - prev_bytes);

When I comment this out, the error goes away. So, I figure I must be writing past the buffer I allocated, but I don't see how. I added some debugging output before the offending line, like so:

cout << ">                 address of `data`: " << static_cast<void*>(data) << endl;
cout << ">                      `prev_bytes`: " << prev_bytes << endl;
cout << ">    address at `data + prev_bytes`: " << static_cast<void*>(data + prev_bytes) << endl;
cout << ">                            `size`: " << size << endl;
cout << "> `sizeof(int) * size - prev_bytes`: " << (sizeof(int) * size - prev_bytes) << endl;
memset(data + prev_bytes, 0, sizeof(int) * size - prev_bytes);

And the output is:

>                 address of `data`: 0xf450f0
>                      `prev_bytes`: 32
>    address at `data + prev_bytes`: 0xf45170
>                            `size`: 16
> `sizeof(int) * size - prev_bytes`: 32
free(): invalid next size (fast): 0x0000000000f45160 ***

To give a little context, data is an array of integers, and I want to keep the first prev_bytes of this array intact, while clearing the rest, i.e. setting to zeroes.

To achieve this, I'm memseting starting at the data pointer offset by prev_bytes, and writing a number of zeroes. That number being: the size of this (dynamically allocated) array, multiplied by sizeof(int) (presumably 4 bytes), minus prev_bytes.

I just don't see how I could be writing past what I've allocated. In case more code is needed, here's the full functions. It just extends an array to double its size.

void extend(int*& data, int& size, int& used) {
    int resize_factor = 2;
    int* new_buffer = new int[size * resize_factor];
    int  prev_bytes = sizeof(int) * size;
    memcpy(new_buffer, data, prev_bytes);
    delete [] data;
    data = new_buffer;
    size *= resize_factor;
    cout << ">                 address of `data`: " << static_cast<void*>(data) << endl;
    cout << ">                      `prev_bytes`: " << prev_bytes << endl;
    cout << ">    address at `data + prev_bytes`: " << static_cast<void*>(data + prev_bytes) << endl;
    cout << ">                            `size`: " << size << endl;
    cout << "> `sizeof(int) * size - prev_bytes`: " << (sizeof(int) * size - prev_bytes) << endl;
    memset(data + prev_bytes, 0, sizeof(int) * size - prev_bytes);
}

Solution

  • The array data is treated as an array of integers. By using pointer arithmetic data + prev_bytes is actually being interepreted as data + prev_bytes * sizeof(int) and you overflow the buffer.

    You can see that by comparing the address of data with the address of data + prev_bytes. It's 128 bytes greater, instead of 32.

    I think it's because you are casting after you add. Try instead to cast before you add.

    static_cast<void*>(data) + prev_bytes