1

In C is it mandatory to check if the realloc function made it?

void *tmp = realloc(data, new_size);
if (tmp == NULL) return 1;
data = tmp;
nowox
  • 25,978
  • 39
  • 143
  • 293
  • 2
    Yes, it is. Just like `malloc`, `realloc` can fail. At least that's what the documentation says. – Jabberwocky May 21 '22 at 19:14
  • 2
    If you ignore the error, the chances are that your program will crash because it tries to access memory via the null pointer. If you're on a system without virtual memory, then you might be able to read via the null pointer, but it won't be what you expected, and writing via the null pointer is not going to work well either. Basically, the answer is "Yes, you always need to check the return value from `realloc()`". – Jonathan Leffler May 21 '22 at 19:40
  • 2
    Technically, it's not mandatory. But it is strongly recommended for any reliable code. – tstanisl May 21 '22 at 20:24
  • 3
    Basically, you can ignore all result values. The C standard does not force you to write good programs. You do not have to check the results of memory allocations, IO operations or any other functions which can potentially fail – 0___________ May 21 '22 at 20:32

4 Answers4

3

In C is it mandatory to check if the realloc function made it?

The quick answer is: NO! checking for failure is not mandatory. If realloc fails, it returns a null pointer, storing it into the original pointer overwrites the previous value, potentially making the block unreachable for later freeing. Dereferencing this null pointer has undefined behavior, a crash on architectures with protected virtual memory. In practice, on these systems with virtual memory, unless you pass an insanely large number for the new size, the call will not fail so you wont get hit by this sloppy code:

data = realloc(data, new_size); // assume realloc succeeds

If you care to be friendly to the next guy trying to debug the program in more stressed environments, you could add:

data = realloc(data, new_size); // assume realloc succeeds
assert(data);

The long answer is: YES you should check for realloc failure in a reliable production program and handle the failure gracefully.

Obviously realloc can fail if you the requested amount of memory is too large for the heap to honor, but it can also fail for internal reasons for requests for smaller amounts, even amounts smaller than the size of the allocated block passed as an argument, even in the absence of heap corruption caused by undefined behavior. There is just no reason to assume that realloc() will always succeed.

If you know the current size allocated for the object you mean to realloc, you can ignore a realloc failure to shrink the object.

For other requests, you should handle handle the error gracefully. If the error causes the function to abort its operation, any memory allocated for the current task should be free'd to avoid memory leaks if the calling program continues. This is a recommendation to avoid memory or resource leaks and allow the program to run reliably for a long time, but depending on your local constraints, you may get away with slack.


To summarize: depending on local constraints (from quick and dirty throw away code to reliable sturdy production code running indefinitely in a life support system), you might not care about the potential improbable failures or it could be mandatory for you to detect, handle and document any unexpected situations.

Detecting and reporting less improbable errors such as fopen() failure to open files, fgets() failure at end of file or scanf() conversion errors from invalid user input is recommended to avoid wasting hours trying to make sense of unexpected behavior, or worse relying on corrupted data that did not produce obviously incorrect results.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 3
    To be fair, not checking for `malloc` result will not lead to any funny problems on a general purpose OS in practice, at worst a segfault. Not checking for IO errors, `scanf` parse errors etc usually does lead to "funny stuff". So there's a level of how bad not checking for errors is. – hyde May 21 '22 at 20:54
  • @hyde: good point. – chqrlie May 21 '22 at 20:57
  • @hyde, moreover, even successful `realloc` does not guarantee lack of out-of-memory .. errors, because modern OSes usually allocate the pages when the data are written. – tstanisl May 21 '22 at 21:31
  • @tstanisl are you sure? – Jabberwocky May 23 '22 at 15:07
  • @Jabberwocky: yes, modern systems with virtual memory may use [memory overcommitment](https://en.wikipedia.org/wiki/Memory_overcommitment). – chqrlie May 23 '22 at 15:39
  • @chqrlie yes, but I mean if you reallocate N bytes and `realloc` returns a non NULL pointer, you can write into all that memory without problems, but then some memory of another process might get paged out if there is really not enough physical memory, right? Otherwise the whole thing would be pointless. – Jabberwocky May 23 '22 at 16:04
  • 1
    @Jabberwocky: yes, more precisely: if `realloc` issued a system call to map new memory pages in the process address space, writing to these pages will cause the system to commit memory to the process, which may require discarding other pages or paging out memory pages to the swapping area (or compressing them). In extreme stress conditions, this may cause a process to be killed, the current one or another one, a notorious game of Russian roulette in the linux world. – chqrlie May 23 '22 at 18:56
0

Is it mandatory to check if realloc worked?

Yes, or at least, as mandatory as is to check any other success/failure return.

realloc can certainly fail, just as malloc can. In fact, realloc can fail even if you're trying to make a block smaller.

Now, if you're working on the assumption that malloc on a virtual memory system can never fail, and if you're not checking the return value from malloc, either, then no, with the same justification, you could skip checking realloc's return value also. (It'd be silly to check realloc's return value but not malloc's.)

In practice, the question of whether to check for memory allocation failure (malloc and/or realloc) on a modern, virtual-memory system is the subject of some debate. There are plenty of programmers who believe that checking the return values is a waste of time, since "malloc never fails". Me, I always check (except in the very most rushed, throwaway code), because even after all these years, the number of times I've said "I'm getting so tired of typing if( … != NULL) all the time!" is still zero, while the number of times that a checked and caught NULL return has alerted me promptly to a bug in my code, and saved me hours of pointless debugging, is countless.

So in summary, and at the risk of repeating myself, I'd say that, yes, it's mandatory. See also Always check malloc'ed memory?

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • 1
    All good advice, but not at all "mandatory". If it were mandatory, it would fail to compile. The word has very specific meaning. "_at least, as mandatory as is to check any other success/failure return._" - i.e. _not_ mandatory. That is all _advisory_. – Clifford May 21 '22 at 23:18
  • 1
    Yes, it all comes down to your definition and interpretation of that word, and I still don't know what the OP's interpretation is/was. I chose to use a slightly informal definition of "mandatory", basically "mandatory under lots of people's — and my own — coding standard", a distinction you acknowledge in your answer. (But I don't think the OP could have meant anything involving "fails to compile", because they wouldn't have had to ask that.) – Steve Summit May 22 '22 at 00:20
  • Understood; I agree that the OP may not understand what "mandatory" actually means, but disagree that it is a matter if interpretation. There are plenty around here who will get very animated about the precise semantics of coding languages - I see no reason not to apply the same rigour to natural language ;-) – Clifford May 22 '22 at 07:21
0

It is a return value from a library function. The language has no knowledge of the semantics of any function and it is not syntactically mandatory to check or use any return value. That is to say it will compile.

However it may be a semantic error not to check, and an unchecked failure may cause unintended runtime behaviour - i.e. a bug. The language does not prevent you from writing bugs.

It may be "mandatory" in a "local" sense, in cases where development is subjected a coding standard that makes it so. Any reasonable coding standard would likely impose such a requirement, and that might be enforced by static analysis tools or peer review used by the development team. But not universally mandatory. You are free to write bad code if such standards are not applied to your project.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

If you use realloc() on a pointer that has not been initialized with either malloc() or calloc(), as far as I know there's no retrospective way to check realloc()'s return value since it will throw an error:

realloc(): invalid pointer Aborted (core dumped)

Example:

int myint = 10;
int * ptr = &myint;
ptr = (int*) realloc(ptr,(2 * sizeof(int)));
Andrés Sanchez
  • 99
  • 1
  • 10