I am attempting to shrink the pointer "ptr" with realloc() as show in this sample code:
char * ptr = malloc(sizeof(char) * 7);
int i;
for(i = 0;i<7;i++){
ptr[i]= "pointer"[i];
}
puts(ptr);
ptr = realloc(ptr,sizeof(char) * 3);
puts(ptr);
free(ptr);
Expecting the code to free the unused memory i thought that it would return the following:
pointer
poi
However, it instead returns this:
pointer
pointer
Is this an error on the compiler's part, or is this an error in my understanding of realloc()?
You misunderstand realloc. realloc does not necessarily move the data to a new location, and since you are shrinking the memory it almost certainly (depending on the implementation) will not. It does not (necessarily) modify the original contents, and in your case it has not. Your program is invoking undefined behavior, and there is no error except in the program. (Invoking puts with a char * that does not point to a null terminated string is an error.)
realloc returns an updated pointer that points to a chunk of memory of (at least) the requested size. It can do so either by allocating a new chunk of memory and deallocating the old one, or by returning the original pointer value (and updating the system's internal bookkeeping information to track the updated size). If it allocates a new chunk of memory, it copies data from the old location; the amount copied is the old size or the new size, whichever is smaller.
char * ptr = malloc(sizeof(char) * 7);
int i;
for(i = 0;i<7;i++){
ptr[i]= "pointer"[i];
}
puts(ptr);
This has undefined behavior. puts requires a pointer to a string, and a string requires a null character '\0' to terminate it. So for a string with a length of 7 characters, you need to allocate 8 bytes. (And once you've done that, you can use strcpy to copy the data.)
It seems to work because there probably just happens to be a null character in the location just past the end of the allocated memory.
ptr = realloc(ptr,sizeof(char) * 3);
puts(ptr);
More undefined behavior. After the realloc call ptr points to (at least) 3 bytes of memory. Since the new size is smaller than the old size, the system is able to place the new chunk in the same place as the old one; it just marks it as having a smaller size.
So by "luck", ptr points to a sequence of characters:
'p', 'o', 'i', 'n', 't', 'e', 'r', '\0'
but only the first 3 of those bytes are in memory that you can safely access.
realloc could have allocated a new chunk of memory, and the data past the end of that chunk could have contained something other than 'n', 't', 'e', 'r', '\0'. For that matter, the memory past the end of the new smaller chunk could have been clobbered even if realloc returned a pointer to the same location.
One more thing: realloc returns a null pointer if it was unable to allocate memory. You should always check for that, even if you're trying to shrink the allocated memory. And if realloc fails, it leaves the original allocated memory alone; you should consider assigning the result to a different pointer object so you can still access the original memory. (Unless you're going to terminate the program anyway; then it doesn't matter.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With