Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does realloc free the former buffer if it fails?

Tags:

realloc

If realloc fails and returns NULL is the former buffer free'd or it is kept intact? I didn't found that particular piece of information in the man page and I'm quite unsure what to do. If memory is freed then double-free could be risky. If not then the leakage would occur.

like image 262
ja.ro Avatar asked Oct 22 '09 12:10

ja.ro


People also ask

Do we have to free after realloc?

Once you call realloc() , you do not have to free() the memory addressed by pointer passed to realloc() - you have to free() the memory addressed by the pointer realloc() returns. (Unless realloc() returns NULL , in which case the original block of memory - passed to realloc() - has to be free() 'd.)

Does realloc erase data?

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.

Does realloc clear old memory?

No, the data will be copied for you into the new block that the returned p points at, before the old block is freed. This all happens before realloc returns, so the new p points to your data still.

Does realloc always succeed?

"There is no reason for realloc()ing to a smaller size will fail." is an assertion without evidence. As the spec for the Standard C library does not require a reduction to never fail, robust code would not assume an error is not possible, even if unlikely.


2 Answers

No, it does not. That aspect has often annoyed me since you can't just use:

if ((buff = realloc (buff, newsize)) == NULL)     return; 

in your code if you want to free the original on failure. Instead you have to do something like:

if ((newbuff = realloc (buff, newsize)) == NULL) {     free (buff);     return; } buff = newbuff; 

Of course, I understand the rationale behind keeping the original buffer intact on failure but my use case has popped up enough that I generally code my own functions to handle that case, something like:

// Attempt re-allocation. If fail, free old buffer, return NULL.  static void *reallocFreeOnFail (void *oldbuff, size_t sz) {     void *newbuff = realloc (oldbuff, sz);     if (newbuff == NULL) free (oldbuff);     return newbuff; }  // Attempt re-allocation. If fail, return original buffer. // Variable ok is set true/false based on success of re-allocation.  static void *reallocLeaveOnFail (void *oldbuff, size_t sz, int *ok) {     void *newbuff = realloc (oldbuff, sz);     if (newbuff == NULL) {         *ok = 0;         return oldbuff;     }      *ok = 1;     return newbuff; } 

The relevant section in the C11 standard states (my italics):

7.20.3.4 The realloc function

If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined. If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged.

like image 56
paxdiablo Avatar answered Nov 24 '22 02:11

paxdiablo


realloc() returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned. If realloc() fails the original block is left untouched; it is not freed or moved.

malloc(3) - Linux man page

like image 36
jldupont Avatar answered Nov 24 '22 03:11

jldupont