Reputation: 1047
How does the realloc function (c), which only takes the length of the new section of memory, copy the old (smaller, to force the situation in question) section of memory to the new one? (this is assuming it needs to, as in, the memory could not be found contiguous to the old block to extend it)
If it coppied the full size (the second arg to realloc) from the smaller section, it would be reading from invalid memory, right?
Thanks, J
EDIT: code illustrating an extreme example:
int main ( void ) {
unsigned int i=0;
void *test_ptr1, *test_ptr2;
// this first bit just finds the size of the available heap, ignore it if you wish
do {
free(test_ptr1);
printf("%u\n",i);
i+=1073741824; // 1GiB
} while ((test_ptr1 = malloc(i)));
i-=1073741824;
do {
free(test_ptr1);
printf("%u\n",i);
i+=1048576; // 1MiB
} while ((test_ptr1 = malloc(i)));
i-=1048576;
do {
free(test_ptr1);
printf("%u\n",i);
i+=1024; // 1KiB
} while ((test_ptr1 = malloc(i)));
i-=1024;
do {
free(test_ptr1);
printf("%u\n",i);
i+=128; // 128B
} while ((test_ptr1 = malloc(i)));
i-=128;
do {
free(test_ptr1);
printf("%u\n",i);
i++; // 1B
} while ((test_ptr1 = malloc(i)));
i--;
// i is now equal to the size of the available heap (I think...)
test_ptr1 = calloc(i-1, 1); // calloc all but one byte of the available heap
test_ptr2 = malloc(1); // malloc the reamining byte
printf("proving calloc: %u\n", ((char *)test_ptr1)[i-2]); // outputs 0, this might be a point of weakness int this program, if this is optimised in any way it fails to demonstrate the effect
*(char *)test_ptr2 = 'c'; // initialise the byte to 'c'
free(test_ptr1); // free the vast majority of the heap
if ((test_ptr1 = realloc(test_ptr2, i-1))) { // realloc the one byte to the space taken up by the previous calloc that was freed in the previous line
printf("realloc success: %c\n", *(char *)test_ptr1); // outputs c, but whats in the rest of this memory section? and more informatively, where was it coppied from?
getc(stdin);
free(test_ptr1);
free(test_ptr2);
return 0;
} else {
printf("realloc failed\n");
free(test_ptr2);
return -1;
}
}
output:
1945305043
1945305044
1945305045
1945305046
1945305047
1945305048
1945305049
1945305050
1945305051
1945305052
1945305053
1945305054
1945305055
1945305056
proving calloc: 0
realloc success: c
Upvotes: 1
Views: 85
Reputation: 13984
If it coppied the full size (the second arg to realloc) from the smaller section, it would be reading from invalid memory, right?
Right you are, take a look at the documentation:
The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the new size is larger, the value of the newly allocated portion is indeterminate.
Upvotes: 1