malloc error checking methods

25,527

Solution 1

How about this wrapper:

void *safe_malloc(size_t n)
{
    void *p = malloc(n);
    if (p == NULL) {
        fprintf(stderr, "Fatal: failed to allocate %zu bytes.\n", n);
        abort();
    }
    return p;
}

Then just use safe_malloc everywhere, and don't worry about the error checking.

Many programs are not written to gracefully handle memory allocation failures, and this solution is just fine for those applications. If your application is able to continue after memory allocation failures, then you probably wouldn't be asking this question.

Solution 2

When you detect an error with malloc(), calloc() and realloc() (i.e they return a NULL pointer), the POSIX98 standard dictates that errno must be set (see man malloc). You can then use the standard function perror() to print the error without the need to do your own formatting. Note that it will automatically print to stderr, no need to bother with that.

Furthermore, If your application considers the error as fatal, then the process must be ended. If your code is located in the main() function, then using return EXIT_FAILURE; is fine, and use exit(EXIT_FAILURE); if not. It is not recommended to exit with your own return code in that case. If the error is not considered as fatal, then it's up to you how to handle it.

Please also note that, when realloc() fails and returns NULL, the old pointer is still valid and must therefore be freed before leaving.

Solution 3

It is not about how you check the error, It is what you do with the error. In all the cases you can see that the common piece of code used is

if (ptr == NULL) {....}

When you encounter the return value is NULL, what you do after that is your personal choice. Some devs even like to assert() the program.

in the meantime gcc sets the errno for you. So you can use that to get more details and use it as well.

In summary you can do whatever suits you most for your program.

Solution 4

Rule #1. Always check malloc's return value (and realloc's) for errors.

Rule #2. Unless you can recover gracefully, always print an error message to stderr, giving relevant information.

Rule #3. Always exit with a nonzero status of there is an error. (The exact nonzero value doesn't matter so much.)

A "wrapper" function is an excellent way of addressing all three rules at the same time, if your program can tolerate exiting precipitously (that is, without saving any in-memory data which might be vital).

There are some exceptions to Rule #2, but they still involve reporting the error somehow (just not necessarily with an immediate fprintf to stderr), so the basic rule stands.

Share:
25,527
rockstar797
Author by

rockstar797

Updated on November 16, 2020

Comments

  • rockstar797
    rockstar797 over 3 years

    I have seen a few different ways of doing malloc error checking. Is one way better than the other? Are some exit codes better than others? Is using fprintf with stderr better than using a printf statement? Is using a return instead of an exit better?

        ptr=(int*)malloc(n*sizeof(int));  //memory allocated using malloc
        if(ptr==NULL)                     
        {
            printf("Error! memory not allocated.");
            exit(0);
        }
    
        ptr=(int*)malloc(n*sizeof(int));  //memory allocated using malloc
        if(ptr==NULL)                     
        {
            printf("Error! memory not allocated.");
            exit(1);
        }
    
        res = malloc(strlen(str1) + strlen(str2) + 1);
        if (!res) {
            fprintf(stderr, "malloc() failed: insufficient memory!\n");
            return EXIT_FAILURE;
        }
    
        ptr=(int*)malloc(n*sizeof(int));  //memory allocated using malloc
        if(ptr==NULL)                     
        {
            printf("Error! memory not allocated.");
            exit(-1);
        }
    
       ptr=(int*)malloc(n*sizeof(int));  //memory allocated using malloc
        if(ptr==NULL)                     
        {
            printf("Error! memory not allocated.");
            exit(EXIT_FAILURE);
        }
    
    char *ptr = (char *)malloc(sizeof(char) * some_int);
    if (ptr == NULL) {
        fprintf(stderr, "failed to allocate memory.\n");
        return -1;
    }
    
    char* allocCharBuffer(size_t numberOfChars) 
    {
        char *ptr = (char *)malloc(sizeof(char) * numberOfChars);
        if (ptr == NULL) {
            fprintf(stderr, "failed to allocate memory.\n");
            exit(-1);
        }
        return ptr;
    }
    
  • kaylum
    kaylum over 8 years
    I wouldn't go as far as to dictate that allocation failures should always be considered fatal. That is really up to the application. The application may have a way to recover such as freeing up some memory and retrying the allocation or retrying with a smaller allocation or even just waiting for a while and trying again later in cases where memory usage across the application may be transient.
  • Magix
    Magix over 8 years
    @M.M I didn't mean to check for errors using errno, but only if errors are detected then perror() will do its job. I will edit to make this clearer
  • Seng Cheong
    Seng Cheong over 8 years
    Downvoter care to explain why you dislike this solution?
  • Magix
    Magix over 8 years
    I downvoted because, depending of the context, the application may need to free some variables before leaving, even in applications which don't need to continue after allocation failures. This is not possible with this wrapper, and may cause memory leaks.
  • Admin
    Admin over 8 years
    I didn't downvote, but aborting the program after an allocation failure is hardly "safe" when you have other memory that needs freed... That aside, you also might want to change %zd to %zu in your printf() format string to match size_t rather than the signed equivalent (ssize_t on a POSIX system).
  • Seng Cheong
    Seng Cheong over 8 years
    @Magix Memory leaks are the least of your worries when your application is out of memory. All of the process's memory is returned to the kernel when it exits anyway.
  • Seng Cheong
    Seng Cheong over 8 years
    @Chrono thanks, changed to %zu. But again, freeing memory before you abort is pointless.
  • Seng Cheong
    Seng Cheong over 8 years
    Also if you are going to downvote this answer for that reason you need to downvote all other answers as well.
  • rockstar797
    rockstar797 over 8 years
    @JonathonReinhart would this function be called like this? safe_malloc(sizeof(n)) Are we assuming this is a char? Wouldn't you need to something a bit different if its int because its bigger?
  • Seng Cheong
    Seng Cheong over 8 years
    @rockstar797 it obviously depends on what you're trying to allocate. As I said, this function is a drop-in replacement for malloc that requires no error checking.
  • Magix
    Magix over 3 years
    Updated : The Posix98 standard actually enforces errno to be set, as described in my answer. See man malloc and the posix standard. Non-compliant implementations are undefined behaviour
  • Folkert van Heusden
    Folkert van Heusden over 3 years
    Please note that fprintf may also perform mallocs. So then that printf may also fail.