Do we lose data in a buffer after realloc'ing?

25,652

Solution 1

A realloc that increases the size of the block will retain the contents of the original memory block. Even if the memory block cannot be resized in placed, then the old data will be copied to the new block. For a realloc that reduces the size of the block, the old data will be truncated.

Note that your call to realloc will mean you lose your data if, for some reason the realloc fails. This is because realloc fails by returning NULL, but in that case the original block of memory is still valid but you can't access it any more since you have overwritten the pointer will the NULL.

The standard pattern is:

newbuffer = realloc(buffer, newsize);
if (newbuffer == NULL)
{
    //handle error
    return ...
}
buffer = newbuffer;

Note also that the casting the return value from malloc is unnecessary in C and that sizeof(char) is, by definition, equal to 1.

Solution 2

Nothing is lost. But you really should test if the realloc() (and the malloc() before) "worked".
Also the cast to the return value of malloc is, at best, redundant, and it may hide an error the compiler would have caught in its absence.

based on the assumption you want strings, your usage of strncpy is wrong

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char *buffer = malloc(3);
    if (buffer == NULL) /* no memory */ exit(EXIT_FAILURE);

    strncpy(buffer, "AB", 2);
    /* ATTENTTION! ATTENTION: your array is not a string.
    ** buffer[2] is not the zero string terminator */

    // buffer = realloc(buffer, 6); /* Will there be any lost here? */
    /* If realloc returns NULL, you've just lost the only pointer to
    ** the allocalted memory, by overwriting it with NULL.
    ** Always `realloc` to a temporary variable */
    char *tmp_buffer = realloc(buffer, 6);
    if (tmp_buffer == NULL) {
        /* realloc failed */
    } else {
        /* realloc worked, no bytes lost */
        buffer = tmp_buffer;
        /* ATTENTION! ATTENTION: buffer is still not a string
        ** buffer[0] is 'A', buffer[1] is 'B',
        ** all other elements of buffer are indeterminate */
    }

    free(buffer);
    return(0);
}
Share:
25,652
Admin
Author by

Admin

Updated on May 30, 2020

Comments

  • Admin
    Admin almost 4 years

    I'm having troubles understanding how realloc works. If I malloc'ed a buffer and copied data to that buffer, let's say "AB":

     +------------+
     | A | B | \0 |
     +------------+
    

    then I realloc'ed the buffer, will there be any lost in the data (even a single byte)?; or it just does expanding the buffer? :

     +------------------------+
     | A | B | \0 | ? | ? | ? |
     +------------------------+
    

    code:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int main(void){
    
        char* buffer    = (char*) malloc( sizeof(char) * 3 );
        strncpy(buffer, "AB", 2);
    
        buffer          = (char*) realloc(buffer, sizeof(char) * 6); /* Will there be any lost here? */
        free(buffer);
        return(0);
    }
    
  • ylun.ca
    ylun.ca over 8 years
    Why can't you do buffer = realloc(buffer, newsize); ?
  • David Heffernan
    David Heffernan over 8 years
    @ylun for the reasons explained in the answer
  • ylun.ca
    ylun.ca over 8 years
    Right so in order to prevent data loss you would first check that the allocation is successful and then reassign, thanks.
  • Kenny Worden
    Kenny Worden about 7 years
    What if you realloc a smaller block of memory?
  • David Heffernan
    David Heffernan about 7 years
    Obviously you lose what you deallocate but you keep the rest