2

Currently Visual C++ is shipped with runtime where malloc() is decorated with __declspec( restrict ).

MSDN says this decoration states to the compiler that a pointer returned by malloc() cannot be aliased by any other pointer. Okay, two subsequent calls to malloc() indeed return distinct pointers. But what happens if I call

void* memory1 = malloc( 10 );
free( memory1 );
void* memory2 = malloc( 10 );
//here memory1 may be equal to memory2

In this case the two pointers can point to the very same location. How does this correlate with cannot be aliased by any other pointer implication of __declspec( restrict )?

sharptooth
  • 167,383
  • 100
  • 513
  • 979

2 Answers2

4

Because once you free(memory1), accessing anything via the memory1 pointer is undefined behavior (nasal demons, and so forth), and hence the compiler can optimize assuming that memory2 is not aliased by any other pointer after the malloc() call.

As for why this matters, assuming the compiler itself has no internal information about the semantics of malloc(), i.e. that it treats it just like any other function, then it cannot assume that the pointer returned is not aliased by any other pointer. The __declspec(restrict) (or equivalently, __attribute__((malloc)) in GCC) tells the compiler that the pointer is not aliased by any other pointer, which allows some optimizations not possible otherwise.

janneb
  • 36,249
  • 2
  • 81
  • 97
  • "Because once you free(memory1), accessing anything via the memory1 pointer is not allowed...": it actually IS ALLOWED, and RESULTS IN UNDEFINED BEHAVIOR. Not allowed IMHO means another thing. "the compiler can optimize assuming that memory2 is not aliased to anything else after the malloc()" ??? That's not clear: what "aliasing"? it has just been allocated! – Emilio Garavaglia Sep 23 '11 at 09:16
  • @Emilio: I don't understand your edited comment. Please clarify? – janneb Sep 23 '11 at 09:19
  • Thanks. Can you clarify the second part of your post? It's to me "obscure" ... (May be just a rewording...) – Emilio Garavaglia Sep 23 '11 at 09:21
  • @Emilio: I reworded it slightly and added some explanation in the second paragraph. Hope that helps. – janneb Sep 23 '11 at 09:25
  • yes, but what does it mean that "the pointer is not aliased by another pointer"?? That was the OP question. – Emilio Garavaglia Sep 23 '11 at 09:45
  • 1
    This suggests a possible example where merely using the value of a freed pointer misbehaves. If the optimizer is assuming there's no aliasing, and you write `if ((memory2 != 0) && (memory2 == memory1))` then the compiler could omit the entire check as always false. I don't know whether MSVC actually does optimize away equality comparisons of non-null `restrict` pointers, but it's a logical consequence of the `restrict`, and it's conforming since `memory1 == memory2` is UB. – Steve Jessop Sep 23 '11 at 10:18
  • @EmilioGaravaglia: TBH, I don't think the OP was asking what pointer aliasing is, but rather how the two pointers are guaranteed not to alias, since they may well point to the same memory address. And that was the question I answered, I believe. – janneb Sep 23 '11 at 10:54
3

The standard has this to say about "object lifetime" (§3.8 in N3290):

The lifetime of an object of type T ends when:
— if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
— the storage which the object occupies is reused or released.

After you've free'd the block pointed to by memory1, that object is dead. It has ceased to exist. Dereferencing that pointer would be undefined behavior.

memory2 could be assigned the same memory address, but it wouldn't "alias" anything: what was at that location has passed away.

Mat
  • 202,337
  • 40
  • 393
  • 406