Re: free'd address still readable?

From: Floyd L. Davidson (floyd_at_barrow.com)
Date: 04/07/04


Date: Wed, 07 Apr 2004 07:33:03 -0800


"Vinay Kurien" <vinayik@charter.net> wrote:
>"Paul Pluzhnikov" <ppluzhnikov-nsp@charter.net> wrote:
>> "Vinay Kurien" <vinayik@charter.net> writes:
>>
>> > Even if that object is free'd ?
>>
>> If the object isn't free()d, the address will be valid.
>> If it is, you can't assume anything.
>
>But even if it is free'd, isn't that address just an index into somwhere
>the available process heap ? Why is it not readable ? Is this behavior
>dependant on the platform ?

It is /totally/ platform dependent. Moreover, it can be
different for unknown reasons on the same platform... and one
possible form of "different" is to appear to do the "right"
thing!

The ISO/ANSI C Standard references the situation you ask about
in two different ways. In "Annex J (informative) Portability
issues",

    J.2 Undefined behavior

 1 The behavior is undefined in the following circumstances:
 ...
          - The value of a pointer that refers to space
            deallocated by a call to the free or realloc
            function is used (7.20.3).

The term "Undefined behavior" is specific, and itself is defined in
the Standard,

    3.4.3
 1 undefined behavior

      behavior, upon use of a nonportable or erroneous program
      construct or of erroneous data, for which this
      International Standard imposes no requirements

 2 NOTE Possible undefined behavior ranges from ignoring the
      situation completely with unpredictable results, to
      behaving during translation or program execution in a
      documented manner characteristic of the environment (with
      or without the issuance of a diagnostic message), to
      terminating a translation or execution (with the issuance
      of a diagnostic message).

 3 EXAMPLE An example of undefined behavior is the behavior
      on integer overflow.

Here is another significant part of the C Standard:

    6.2.4 Storage durations of objects

 1 An object has a storage duration that determines its
      lifetime. There are three storage durations: static,
      automatic, and allocated. Allocated storage is described
      in 7.20.3.

 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,25) and retains its last-stored value throughout
      its lifetime.26) 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
      reaches the end of its lifetime.

Hence, again, any attempt to use a pointer that has been free'd
results in "undefined behavior", specifically because the pointer
is indeterminate.

And, here's the definition of "indeterminate value", along with
"unspecified value" and "trap representation",

    3.17.2
 1 indeterminate value
      either an unspecified value or a trap representation
    3.17.3
 1 unspecified value
      valid value of the relevant type where this International
      Standard imposes no requirements on which value is chosen
      in any instance

 2 NOTE An unspecified value cannot be a trap representation.

 ...

    6.2.6 Representations of types
    6.2.6.1 General

 5 Certain object representations need not represent a value
      of the object type. If the stored value of an object has
      such a representation and is read by an lvalue expression
      that does not have character type, the behavior is
      undefined. If such a representation is produced by a side
      effect that modifies all or any part of the object by an
      lvalue expression that does not have character type, the
      behavior is undefined.41) Such a representation is called
      a trap representation.

>I guess it comes down to something as simple as:

It's hard not to add a giggle at this point, after I've injected
all of the above, about the idea that it is "something as simple
as"... :-)

>//Every time I allocate 'struct something' I set a unique key
>struct something *a = (struct something*)malloc(10);
>a->key = 0xAABBCCDD;

Ouch. You've put an address to a struct object into pointer
variable 'a', but you've done *nothing* to set a member of that
struct named 'key' to be anything in particular... If 'key' is
indeed a pointer, then using it in any way fits the descriptions
above just as much as the pointer to the struct 'a' does; which
means it is indeterminate until you initialize it with the
address of a valid object.

But, yes you do get a unique address from malloc, and it has
certain guarantees beyond being unique. It will be aligned
properly, will be contiguous, and disjoint from any other
object.

>//Everytime I free 'struct something', I memset it.
>free(a);
>memset(a, 0, sizeof(struct something);

Undefined behavior... you are using the value of 'a' after it
has been deallocated. It is not possible to predict what will
happen (other than knowing it *will* bite you sooner or later).

><snip>
>if (a->key != 0xAABBCCDD) { //Is this legal ?

Just as undefined as above. And that would be true even if you
had properly set a->key to a valid pointer.

> //object instance is free'd
> return;
>}
>
>will this SIGSEGV ?

It might. It doesn't have to. One of the things that
"undefined behavior" can do, is exactly what you'd want to
happen if it were defined. Hence your program may work
"perfectly" for 20 years too.

>In my scenario the only difference is that I send the address in a, to
>another
>process, which that process echos back at a later time. At that later time,
>all
>
>I want to know is if that adress still stores an instance of 'struct
>something' ... If not, I exit.

It is valid until it is deallocated. Hence, if you call free()
or realloc() with that address as a parameter, it may or may
not, in the case of realloc(), be invalid.

>> > My issue is that, I pass around the context(virtual address) of that object
>> > to other processes and when the context is returned to the process that
>> > allocated the object I am not sure if that object has been free'd or not. Is
>>
>> Huh? You can't pass pointers to memory allocated in one process to
>> another -- the address will not be valid in the other process.
>
>I donot want the other process to try and dereference this memory. I just
>want it to echo back the address to the process that allocated this object.

OK, that will work, as long as the address has not been
deallocated...

You'll most likely need to keep a table of valid pointers, so
that you can determine if any given address has been free'd or
not.

--
Floyd L. Davidson           <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska)                         floyd@barrow.com


Relevant Pages

  • Re: using "!!" in "c"
    ... What %p prints can be in any format as long as it can be read by a %p in a scanf on that implementation and yield the original pointer. ... passing this to printfinvokes undefined behavior. ... not to produce a trap representation then it is only implementation defined behaviour IIRC. ...
    (comp.lang.c)
  • Re: Controlling Static Data and Memory Organization...If Possible...
    ... resides invokes the wrath of undefined behavior because you are ... different pages of memory, and for the physical location of those pages ... to do with what "exactly" a pointer is physically in your program ... character at an address that is 1 higher than the one before it. ...
    (comp.lang.c)
  • Re: Please explain the output
    ... >>> invoke undefined behavior though. ... >> pointer to a different object or incomplete type. ... >> happen to be aligned sufficiently for an int. ... > struct foo ...
    (comp.lang.c)
  • Re: gcc knows about malloc()
    ... A pointer to a function of one type may be converted to a pointer to a ... no syntax errors doesn't cause undefined behavior. ... types are supposed to have the same representation. ... specifiers or qualifiers ...
    (comp.lang.c)
  • Re: Highly efficient string reversal code
    ... uninitialised pointer. ... NOTE Possible undefined behavior ranges from ignoring the ... very beginning of a segment. ... standard is specifically designed to allow such an implementation. ...
    (comp.lang.c)