开发者

How detect malloc failure?

What is the portable way to ch开发者_JAVA百科eck whether malloc failed to allocate non-zero memory block?


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


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."


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!


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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜