rockstar797
rockstar797

Reputation: 147

malloc error checking methods

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;
}

Upvotes: 11

Views: 39316

Answers (5)

Magix
Magix

Reputation: 5339

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.

Upvotes: 13

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137398

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.

Upvotes: 15

Steve Summit
Steve Summit

Reputation: 47952

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.

Upvotes: 1

Petr Skocik
Petr Skocik

Reputation: 60068

perror("more details"); 

will (attempt to) print the error (as per the errno) to stderr. You can use that.

static void die(const char* msg){ perror(msg); exit(1); }  

You could also save the errno and translate it to a BSD style sysexits.h code or just somehow linearly serialize it to the parent process (by exiting with the errno or a linear translation thereof).

Upvotes: 0

Fawzan
Fawzan

Reputation: 4849

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.

Upvotes: 2

Related Questions