Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the compiler allowed to recycle freed pointer variables?

It has been claimed that

a compiler is free to reuse the pointer variable for some other purpose after the realloc being freed, so you have no guarantee that it has the same value as it did before

ie

void *p = malloc(42);
uintptr_t address = (uintptr_t)p;
free(p);

// [...] stuff unrelated to p or address

assert((uintptr_t)p == address);

might fail.

C11 annex J.2 reads

The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3) [is undefined]

but the annex is of course not normative.

Annex L.3 (which is normative, but optional) tells us that if

The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3).

the result is permitted to be critical undefined behaviour.

This confirms the claim, but I'd like to see an appropriate quote from the standard proper instead of the annex.

like image 872
Christoph Avatar asked Sep 27 '14 10:09

Christoph


1 Answers

Upon an object reaching the end of its lifetime, all pointers to it become indeterminate. This applies to block-scope variables and to malloced memory just the same. The applicable clause is, in C11, 6.2.4:2.

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

Using indeterminate memory for anything, including apparently harmless comparison or arithmetic, is undefined behavior (in C90; later standards complicate the matter terribly but compilers continue to treat usage of indeterminate memory as undefined behavior).

As an example, how about the following program printing that p and q are both different and the same? The results of execution with various compilers are shown here.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(int argc, char *argv[]) {
  char *p, *q;
  uintptr_t pv, qv;
  {
    char a = 3;
    p = &a;
    pv = (uintptr_t)p;
  }
  {
    char b = 4;
    q = &b;
    qv = (uintptr_t)q;
  }
  printf("Roses are red,\nViolets are blue,\n");
  if (p == q)
    printf ("This poem is lame,\nIt doesn't even rhyme.\n");
  else {
    printf("%p is different from %p\n", (void*)p, (void*)q);
    printf("%"PRIxPTR" is not the same as %"PRIxPTR"\n", pv, qv);
  }
}
like image 70
Pascal Cuoq Avatar answered Sep 17 '22 23:09

Pascal Cuoq