How detect malloc failure?

后端 未结 5 1507
情歌与酒
情歌与酒 2020-12-03 13:31

What is the portable way to check whether malloc failed to allocate non-zero memory block?

相关标签:
5条回答
  • 2020-12-03 13:46

    I always do this:

    tok = malloc( sizeof( char ) * ( strlen(tc) + 1 ) );
    
    if( tok == NULL )
    {
         /* Malloc failed, deal with it */
    }
    

    Some people do tok = (type) malloc( ... ) but you should cast the result because apparently it covers up some nasty errors. I will do some research and see if I can find out exactly what they are.

    Edit:

    Casting malloc can hide a missing #include <stdlib.h>

    I found this link which contained a very good explanation:

    http://cboard.cprogramming.com/faq-board/25799-faq-casting-malloc.html

    "So when you say this (char*)malloc(10)

    You're saying that you take whatever malloc returns, convert it to a char*, and assign that to the variable in question.

    This is all well and good if malloc is prototyped properly (by including stdlib.h), where it's defined as returning void*.

    The problem comes in when you fail to include stdlib.h, and the compiler initially assumes that malloc returns an int. The real problem is, you DONT get any warning from the compiler.

    You merrily then convert that int to a char* (via the cast). On machines where sizeof(char*) is different from sizeof(int), the code is seriously broken.

    Now if you just have char *var = malloc( 10 ); And you miss out the include , you will get a warning from the compiler."

    0 讨论(0)
  • 2020-12-03 13:55

    Sure. The portable way is to test if malloc(...) returns NULL.

    0 讨论(0)
  • 2020-12-03 13:57

    You can detect failure when:

    malloc(n) returns NULL

    This is the most common and reliable test to detect an allocation failure. If you want to be portable beyond POSIX/SUS, I wouldn't trust errno though. If you need detail, say for logging, I'd zero errno before the call, see if it changed, then maybe log that.

    malloc(n) returns a non-NULL address which is not backed by actual memory

    Touch it and see if you get killed by the OS. Yes, this can happen. It's called memory overcommit and resembles fractional reserve banking. It's the optimistic approach of an OS or hypervisor to return addresses to virtual memory they're gambling they won't ever have to actually provide. This happens on Linux, VMware. (I can't find any explicit evidence of Windows overcommitting, although requested pages are only "committed" when they are touched.)

    The question then is "how do I portably detect if my program is about to crash on accessing an address I got from the malloc I previously trusted like a teenage crush?". One way might be to read() a random file into the test area and see if the OS returns EINVAL or equivalent.

    For extra points,

    malloc(0) returns NULL and leaves errno undefined

    I know the question asked for "non-zero [sized] memory block", but this is interesting. Consider a SUS-compliant allocator that intends to return non-NULL for a zero-sized allocation (it can do that), but then it fails, so it has to return NULL. And it could try to set errno. Is that a failure? I think Hoare says we paid a billion dollars for this ambiguity. So, calling malloc(0) is not portable and the questioner probably knew that!

    0 讨论(0)
  • 2020-12-03 14:05

    malloc(n) returns NULL on failure.
    malloc(0) may return NULL.

    To detect failure:

    void* ptr = malloc(n);
    if (ptr == NULL && n > 0) Handle_Failure();
    

    Notes:

    As in OP's case: "... allocate non-zero memory block", often code is such that a 0 allocation request can not occur and so the 0 test is not needed.

    size_t nstr = strlen(some_string) + 1;
    void* ptrstr = malloc(nstr);
    if (ptrstr == NULL) Handle_Failure();
    

    Some systems set errno on failure, but not all. Setting errno due to memory allocation failure is not specified in the C11 spec.

    malloc(n) expects n to be the unsigned type size_t. Using an int n with a negative value will certainly convert to some large unsigned value and then likely fail the memory allocation.

    0 讨论(0)
  • 2020-12-03 14:10

    According to the Single Unix Specification, malloc will return NULL and set errno when it fails.

    0 讨论(0)
提交回复
热议问题