34

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.

ja.ro
  • 466
  • 1
  • 4
  • 5

4 Answers4

34

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • The duplicate conditional jump (checking against `NULL` once before calling `free` and again inside `free`) costs more in the common case (where the pointer is not `NULL`) and only helps minimally in the rare case (where the pointer is `NULL`). I would say it's a net loss. – R.. GitHub STOP HELPING ICE Sep 04 '11 at 02:03
  • Actually, that's a good point, @R. The predominant case will almost certainly have a non-NULL `old` so my check doesn't really buy that much. I'll get rid of it. – paxdiablo Sep 04 '11 at 06:33
  • 1
    You should probably also skip calling `realloc` and just call `free(old)` if `sz==0`. This is because there's some degree of disagreement on what `realloc` returning 0 can mean. Some people claim it's legal to return 0 (and not set `errno`) if the memory was successfully resized to size 0 and the implementation has `malloc(0)==NULL`, in which case the subsequent `free(old)` would be a dangerous double-free. I would write the function: `void *new=0; if (!sz || !(new=realloc(old,sz))) free(old); return new;` – R.. GitHub STOP HELPING ICE Sep 04 '11 at 12:41
  • Actually to give a safe "success" return on `realloc`-to-size-zero you probably need to `return malloc(1);` in this case... uhg.. – R.. GitHub STOP HELPING ICE Sep 04 '11 at 12:47
  • @R..: Troublingly, [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html) says that `realloc(ptr, 0)` can fail to free `ptr` and should not be used, but [`realloc(3)`](https://linux.die.net/man/3/realloc) says it is "equivalent to `free(ptr)`," which cannot fail because `free()` is `void` and is unable to indicate failure. – Kevin Feb 12 '19 at 16:49
  • If you're on a BSD, or have libbsd avaiable (it's available in most Unix systems, including GNU/Linux distros), you can use reallocf(3). – alx - recommends codidact Feb 16 '23 at 15:08
5

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

Ry-
  • 218,210
  • 55
  • 464
  • 476
jldupont
  • 93,734
  • 56
  • 203
  • 318
2

No. No change of the former buffer is done if realloc() failed.

man realloc(3):

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.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
Test
  • 1,697
  • 1
  • 11
  • 10
1

No.It won't. Realloc changes increases/decreases the dynamic memory allocated via malloc or calloc. It will return NULL in case realloc fails while increasing memory but it won't change previously allocated memory. As Realloc computes new memory allocation from the base address of previously allocated memory, it does not perform any operation on the memory

shil.ban
  • 11
  • 1