Have you experienced malloc failing a lot? How do you test to ensure error handling code paths work as expected?
Have you read 'notes' section of Linux malloc manpage? It says:
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. In case it turns out that the system is out of memory, one or more processes will be killed by the OOM killer.
Edit. It is impossible for malloc to fail (at least on linux) [1]. Seems rather pointless checking for something that can’t happen.
Actually the real issue here is that you should be aware that on some systems malloc might fail and not segfault.
#include <stdlib.h>
#include <stdio.h>
#include <sys/resource.h>
const int SIZE = 64*1024*1024;
int main() {
char *buffer = NULL;
struct rlimit r;
/* Limit all memory to 1024 bytes */
r.rlim_cur = 1024;
r.rlim_max = 1024;
if (setrlimit(RLIMIT_AS, &r) == -1 ) {
perror("setrlimit(RLIMIT_AS) error\n");
exit(EXIT_FAILURE);
}
if ( (buffer = malloc( sizeof(long) * SIZE) ) == NULL) {
perror("malloc() failed\n");
exit(EXIT_FAILURE);
}
free(buffer);
printf("Malloc worked\n");
return 0;
}
Here's the output: %cc fail.c
%./a.out
malloc() failed
: Cannot allocate memory
If malloc failure testing is important to you, then you'll need some way to replace your use of the system malloc/free with special versions of your own. (Eg, through function pointers, or LD_PRELOAD.) Your own versions can be crafted to insert faults in just the right spots.It's tedious work.
I was under the impression that compiler optimisation often removed any NULL checks anyway [1].
1. http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
Goodness.
No, you are misunderstanding the example. The optimizer did not introduce a bug by removing a NULL check. The code had a bug because it dereferenced the pointer before checking for NULL.
Are there any modern platforms where dereferncing a NULL pointer will not cause a crash?
Edit. Answering my own question it looks like ARM is one [1].
1. https://www.securecoding.cert.org/confluence/display/c/EXP34...
Incorrect. The example code did not check for a null pointer. It dereferenced a pointer, which implies that the pointer will never be null, and then it pointlessly checked for null on something that could not have been null. The optimizer in fact made the code more clear and easier to read, while maintaining correctness.
"While this is intentionally a simple and contrived example, this sort of thing happens all the time with inlining: inlining a function often exposes a number of secondary optimization opportunities. This means that if the optimizer decides to inline a function, a variety of local optimizations can kick in, which change the behavior of the code. This is both perfectly valid according to the standard, and important for performance in practice.”
In practice derefencing a NULL pointer on any x86 platform will always cause a crash (defined undefined behaviour I guess), but you can’t assume this on other platforms (ARM seems to be the big one).
I have to say before today I had assumed dereferncing a NULL pointer would always cause a segfault. It is always good to learn something new.