0

I've always done checking what malloc returns like this:

void *p; 
p = malloc(100);
if (p) 
{ 
  perror("malloc"); 
  return false;
}

But one thought, why do it if you can guarantee getting memory?

#define GET_MEM(p,s,i) do{for(p=NULL,i=0;!(p=calloc(1,s))&&i<5;perror("calloc"),i++)}while(0)

What are the pros and cons of such a decision? How should it be done?

Ivan Ivanovich
  • 880
  • 1
  • 6
  • 15
  • `do { } while(0)` ?! – Sebastian Jan 21 '15 at 09:06
  • it is from freebsd source – Ivan Ivanovich Jan 21 '15 at 09:07
  • the free macro is wrong, it should be `if(p)` instead of `if(!p)`. Also it is unnecessary, because you are allowed to do a `free(NULL);`. – mch Jan 21 '15 at 09:08
  • @IvanIvanovich, yeah, because of this: [do { … } while (0) — what is it good for?](http://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for). However, if you do not understand what it does, do not use it. – Sebastian Jan 21 '15 at 09:09
  • 1
    If I'm reading this right, the macro retries `calloc` 5 times. I don't see how that guarantees getting memory. – user3386109 Jan 21 '15 at 09:16
  • 2
    1. If you know you always get memory you don't need error handling and no wrapper, so I do not understand your question to begin with. 2 In your first example, `if (p) `must be changed to `if(!p)`. 3. If calloc fails once, it will fail most likely 5 times as well, multiple tries don't make much sense. 4. Why do you pass i in as a parameter? It should be declared a local variable in the do loop. – Peter - Reinstate Monica Jan 21 '15 at 09:21
  • 1
    Apart from my objections above, I like error handling wrapper macros. SGI had a header for that iirc, 20 years ago, and so does Stevens in his books. It makes the important code more readable by reducing the noise. For larger projects more elaborate error handlig (logging etc.) makes such macros more difficult to use, but for small, isolated programs it can be nice. – Peter - Reinstate Monica Jan 21 '15 at 09:24

2 Answers2

2

why do it if you can guarantee getting memory.

Your assumption is wrong.

malloc() calloc() and realloc() might fail. So when the memory requested by you is not successfully allocated then these functions retrun NULL. If this check is not there then you go ahead and start writing to this memory location which is not allocated which causes undefined behavior.

If your question is about why there is a do while loop in the macro. The below link explains it really well

do { ... } while (0) — what is it good for?

Community
  • 1
  • 1
Gopi
  • 19,784
  • 4
  • 24
  • 36
1

First of all, this is incorrect and actually does the opposite of what it should:

void *p; 
p = malloc(100);
if (p) 
{ 
  perror("malloc"); 
  return false;
}

This if statement says: if( malloc succeeded ){ return AN_ERROR; }

It should say:

void *p; 
p = malloc(100);
if( NULL == p ) 
{ 
  perror("malloc"); 
  return false;
}

Now as for your question:

But one thought, why do it if you can guarantee getting memory?

As Gopi stated, you cannot guarantee getting memory. You very well can run out of memory and thus be unable to allocate anymore. It is unlikely that you will use up all of the available memory for the process, but it could happen. This is why checking the return of functions like like malloc(), calloc(), and realloc() is essential.

Any of these memory allocation functions can fail if there is not enough memory and you must be prepared to handle that. Let us suppose you allocate space for string, but malloc fails and you do not check for that:

int main(int argc, char *argv[]){
    char stringToCopy[] = "Some very long string would be here ...";
    char *stringBuffer = malloc( 1000 ); // 1000 char buffer
    // Malloc failed and we did not check for it
    strncpy(stringBuffer, stringToCopy); /* UNDEFINED BEHAVIOUR */
    return 0;
}

So in this situation, malloc failed and we proceeded to attempt to copy the string to the buffer anyway. As soon as we begin doing that, we cause undefined behavior. Typically this kind of action would cause the program to crash due to a Segmentation Fault.

This can be serious and can result in the loss of data or the loss of service. At a minimum, a segmentation fault would inconvenience the user.

As some general rules: Always check the return values of malloc(), calloc() and realloc(); Never blindly trust that these functions were successful.

Whether you choose to do this check inside of a macro or not is your own choice (there aren't many advantages/disadvantages), but just make sure you perform the check and you perform it properly.

Spencer D
  • 3,376
  • 2
  • 27
  • 43