Stephen L. said:
Keith Thompson wrote: [...]
even if the bits composing that value don't change. Any reference to
an indeterminate value invokes undefined behavior. You're very likely
to get away with it on most real-world implementations, but a
conforming implementation could cause a trap on the following code:
free(p);
p;
My question is simply, how does the compiler
_know_ p's value has been `free()'d (I'm not
trying to be silly). Suppose the call to `free()'
was made by some other function, such that -
some_function_which_calls_free(p);
p;
The compiler very likely doesn't "know" that p's value has been
free()'d.
It's possible, in a conforming implementation, for the runtime system
to keep track of all allocated memory (stack, heap, static storage,
whatever), so it knows, for any given pointer value, whether it points
to a memory location which the current program is allowed to
reference. Such an implementation could check, on each reference to
an address value, whether the address is either a null pointer or a
pointer to a valid memory location, and cause a trap if it isn't.
This tracking and checking could be implemented either in software
(for an aggressive debugging implementation) or in hardware.
IBM's AS/400 has been cited as a system that does some of this kind of
thing (pointers are some kind of descriptor, not physical memory
addresses); I don't remember whether it does this particular check.
It's also possible (and, as it happens, more likely) for an
implementation to ignore the issue altogether. If a program
references, or even dereferences, an invalid pointer value, it invokes
undefined behavior. There is no requirement for the implementation to
do anything in particular. That's what "undefined behavior" means.
Also, the OP never mentioned dereferencing `p',
only seeing if his _shadow_ pointer variable
pointed to the same object as `p' once did -
a simple arithmetic comparison.
A comparison between two pointers is a pointer comparison, not an
arithmetic comparison. One of the most important things to remember
is that pointers are not numbers, even though they may share some of
the characteristics of numbers (they're made of bits and you can
perform some very limited arithmetic operations on them).
But for example:
int *p = malloc(sizeof *p); /* assume malloc() succeeds */
int *q = p;
free(p);
After the call to free(), any reference to the value of either p or q
(including a simple pointer equality comparison) will invoke undefined
behavior.