Andrew Cheong Andrew Cheong -4 years ago 222
C++ Question

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
memset
ing 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);
}

Answer Source

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
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download