Can I rely on malloc returning NULL?
I read that on Unix systems, malloc
can return a non-NULL pointer even if the memory is not actually available, and trying to use the memory later on will trigger an error. Since I cannot catch such an error by checking for NULL, I wonder how useful it is to check for NULL at all?
On a related note, Herb Sutter says that handling C++ memory errors is futile, because the system will go into spasms of paging long before an exception will actually occur. Does this apply to malloc
as well?
Quoting Linux manuals:
By default, Linux follows an optimistic memory allocation strategy. This means that when malloc()
returns non- NULL
there is no guarantee that the memory really is available. This is a really bad bug. In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM killer. In case Linux is employed under circumstances where it would be less desirable to suddenly lose some randomly picked processes, and moreover the kernel version is sufficiently recent, one can switch off this overcommitting behavior using a command like:
# echo 2 > /proc/sys/vm/overcommit_memory
You ought to check for NULL
return, especially on 32-bit systems, as the process address space could be exhausted far before the RAM: on 32-bit Linux for example, user processes might have usable address space of 2G - 3G as opposed to over 4G of total RAM. On 64-bit systems it might be useless to check the malloc
return code, but might be considered good practice anyway, and it does make your program more portable. And, remember, dereferencing the null pointer kills your process certainly; some swapping might not hurt much compared to that.
If malloc
happens to return NULL
when one tries to allocate only a small amount of memory, then one must be cautious when trying to recover from the error condition as any subsequent malloc
can fail too, until enough memory is available.
The default C++ operator new
is often a wrapper over the same allocation mechanisms employed by malloc()
.
On Linux, you can indeed not rely on malloc
returning NULL
if sufficient memory is not available due to the kernel's overallocation strategy, but you should still check for it because in some circumstances malloc
will return NULL
, eg when you ask for more memory than is available in the machine in total. The Linux malloc(3)
manpage calls the overallocation "a really bad bug" and contains advice on how to turn it off.
I've never heard about this behavior also occurring in other Unix variants.
As for the "spasms of paging", that depends on the machine setup. Eg, I tend not to setup a swap partition on laptop Linux installations, since the exact behavior you fear might kill the hard disk. I would still like the C/C++ programs that I run to check malloc
return values, give appropriate error messages and when possible clean up after themselves.
Checking for the return of malloc
doesn't help you much by its own to make your allocations safer or less error prone. It can even be a trap if this is the only test that you implement.
When called with an argument of 0
the standard allows malloc
to return a sort of unique address, which is not a null pointer and which you don't have the right to access, nevertheless. So if you just test if the return is 0
but don't test the arguments to malloc
, calloc
or realloc
you might encounter a segfault much later.
This error condition (memory exhausted) is quite rare in "hosted" environments. Usually you are in trouble long before you hassle with this kind of error. (But if you are writing runtime libraries, are a kernel hacker or rocket builder this is different, and there the test makes perfect sense.)
People then tend to decorate their code with complicated captures of that error condition that span several lines, doing perror
and stuff like that, that can have an impact on the readability of the code.
I think that this "check the return of malloc
" is much overestimated, sometimes even defended quite dogmatically. Other things are much more important:
struct
s are an important cause of errors that are difficult to find. malloc
and Co. if this is a compile time constant like sizof toto
there can't be a problem, but always ensure that your vector allocation handles the zero case properly. An easy thing to check for return of malloc
is to wrap it up with something like memset(malloc(n), 0, 1)
. This just writes a 0
in the first byte and crashes nicely if malloc
had an error or n
was 0
to start with.
上一篇: std :: make之间的区别
下一篇: 我可以依靠malloc返回NULL吗?