[LLVMdev] optimization assumes malloc return is non-null

Mike Stump mrs at apple.com
Thu May 1 11:42:56 PDT 2008


On Apr 30, 2008, at 2:20 PM, Jonathan S. Shapiro wrote:
> The standard library specification of malloc() clearly requires that  
> it
> allocates storage

No, your interpretation is wrong.  When the standard says:

                void *malloc(size_t size);

        Description

        [#2] The malloc function allocates space for an object

they don't mean that the malloc function allocates space for an  
object.  What they mean is that you cannot write a program that can  
notice that it didn't allocate space for an object.  The difference is  
subtle, but important.

As an example, compare:

#include <stdlib.h>

  void *vp;

int main(int argc, char** argv){
   if((vp=malloc(sizeof(int))) == NULL){ return 0; }
   else{ return 1; }
}

with -fwhole-program the call to malloc goes away.  Without it, it  
stays.

If we change it to:

#include <stdlib.h>

void * volatile vp;

int foo(int argc, char** argv){
   if((vp=malloc(sizeof(int))) == NULL){ return 0; }
   else{ return 1; }
}

it stays.  If change it to:

#include <stdlib.h>

void * volatile vp;

int main(int argc, char** argv){
   if((vp=malloc(sizeof(int))) == NULL){ return 0; }
   else{ return 1; }
}

it then stays.  This is because you're allowed to observe malloc  
through vp as it is volatile.  Observing the program with writes and  
reads to volatile variables and the I/O behavior of the program are  
only ways in which you get to observe the program.

> I do not believe that any such overt statement is required in order  
> for it to be clear that malloc() is stateful.

You can observe the behavior with I/O and volatiles, all that you  
observe meets the requirements for the semantics according the to  
standard.  malloc need preserve no state or even change state.  The  
standard has no mechanism to require that.  It only says the program  
is required to behave as if describe by the standard.

> The functional description of malloc() and free() clearly cannot be  
> satisfied under the C abstract machine without mutation of at least  
> one object.

Wrong.  In int main() { malloc (4); return 0; } there are 0 writes to  
volatile storage.  There are 0 input routines called, there are 0  
output routines called.  The abstract semantics are return 0 to the  
environment with no input and no output.  Any program that does that,  
is a valid compilation of the code.

Another equally valid translation would be:

int d[100];

int foo() { return 100; }

main() {
   for (i = 0; i<foo(); ++i)
     d[i] = i;
   return 0;
}

thats because the abstract semantics of that program are exactly  
identical to the required abstract semantics of the first.

> Setting the matter of the standard entirely aside, the currently

> implemented behavior deviates so blatantly from common sense

Most people have no clue just what as if means.  People that write  
compilers are expected to know what it means.  If one doesn't, they  
should learn.

> and universal convention that it really must be viewed as a bug.

You can state the required abstract semantics of the program and you  
can state the actual semantics of the translation and we can string  
compare them, if they are identical, we get to say, that is a valid  
compilation of the code.



More information about the llvm-dev mailing list