Should we check if memory allocations fail?

2019-02-06 08:20发布

I've seen a lot of code that checks for NULL pointers whenever an allocation is made. This makes the code verbose, and if it's not done consistently, only when the programmer felt like it, doesn't even ensure that the program won't crash when the address space runs out. Besides, if the program can't make more allocations, it wouldn't be able to do its function anyway, right?

So my question is, isn't it better for most programs not to check at all and just let the program crash if memory runs out? At least the code is more readable that way.

Note

I'm talking about desktop apps that run on modern computers (at least 2 GB address space), and that most definitely don't operate space shuttles, life support systems, or BP's oil platforms. Most importantly I'm talking about programs that use malloc but never really go above 5 MB of memory usage.

7条回答
一纸荒年 Trace。
2楼-- · 2019-02-06 09:01

Yes, you should check for a null return value from malloc. Even if you can't recover from the failure of memory allocation you should explicitly exit. Carrying on as though memory allocation had succeeded leaves your application in an inconsistent state and is likely to cause "undefined behavior" which should be avoided.

For example, you may end up writing inconsistent data to external storage which may hinder the ability of the next run of the application to recover. It's much safer to exit swiftly in a more controlled fashion.

Many applications that want to exit on allocation failure wrap malloc in a function that checks the return value and explicitly aborts on failure.

Arguably, this is one advantage of the C++ default new approach to throw an exception on allocation failure. It requires no effort to exit on memory allocation failure.

查看更多
冷血范
3楼-- · 2019-02-06 09:02

Similar to Dave's approach above, but adds a macro that automatically passes the file name and line number to our allocation routine so that we can report that information in the event of a failure.

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

#define ZMALLOC(theSize) zmalloc(__FILE__, __LINE__, theSize)

static void *zmalloc(const char *file, int line, int size)
{
   void *ptr = malloc(size);

   if(!ptr)
   {
      printf("Could not allocate: %d bytes (%s:%d)\n", size, file, line);
      exit(1);
   }

   return(ptr);
}

int main()
{
   /* -- Set 'forceFailure' to a non-zero value in order to observe
         how 'zmalloc' behaves when it cannot allocate the
         requested memory -- */

   int bytes        = 10 * sizeof(int);
   int forceFailure = 0;
   int *anArray     = NULL;

   if(forceFailure)
      bytes = -1;

   anArray = ZMALLOC(bytes);

   free(anArray);

   return(0);
}
查看更多
虎瘦雄心在
4楼-- · 2019-02-06 09:14

but it is much more difficult to troubleshoot if you don't log where the malloc failed.

failed to allocate memory in line XX is to prefer than just to crash.

查看更多
【Aperson】
5楼-- · 2019-02-06 09:14

I'd like to add that edge cases should always be checked even if you think they are safe or cannot lead to other issues than a crash. Null pointer dereference can potentially be exploited (http://uninformed.org/?v=4&a=5&t=sumry).

查看更多
▲ chillily
6楼-- · 2019-02-06 09:15

Always check the return value, but for clarity, it's common to wrap malloc() in a function which never returns NULL:

void *
emalloc(size_t amt){
    void *v = malloc(amt);  
    if(!v){
        fprintf(stderr, "out of mem\n");
        exit(EXIT_FAILURE);
    }
    return v;
}

Then, later you can use

char *foo = emalloc(56);
foo[12] = 'A';

With no guilty conscience.

查看更多
beautiful°
7楼-- · 2019-02-06 09:17

You should definitely check the return value for malloc. Helpful in debugging and the code becomes robust.

Always check malloc'ed memory?

查看更多
登录 后发表回答