Re: How to know the memory pointed by a ptr is freed?
From: RCollins (rcoll_at_nospam.theriver.com)
Date: 08/20/04
- Next message: RCollins: "Re: How to know the memory pointed by a ptr is freed?"
- Previous message: Mabden: "Re: Is it possible to get the caller's name in C ?"
- In reply to: Keith Thompson: "Re: How to know the memory pointed by a ptr is freed?"
- Next in thread: Keith Thompson: "Re: How to know the memory pointed by a ptr is freed?"
- Reply: Keith Thompson: "Re: How to know the memory pointed by a ptr is freed?"
- Reply: Martin Ambuhl: "Re: How to know the memory pointed by a ptr is freed?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Thu, 19 Aug 2004 17:38:49 -0700
Keith Thompson wrote:
> RCollins <rcoll@nospam.theriver.com> writes:
>
>>Flash Gordon wrote:
>
> [...]
>
>>>You failed to include stdlib.h which is required for malloc. Your
>>>compiler was required to generate a diagnostic for this line if invoked
>>>in ANSI/ISO mode.
>>
>>Let's not nit-pic the trivialities; this is example code, not
>>a lesson for a newbie.
>
>
> If you don't want trivialities nit-picked, I humbly submit that you've
> come to the wrong newsgroup. 8-)}
I think you are right ...
>
> [...]
>
>>>BANG. The pointer might be loaded in to an address register causing
>>>the
>>>program to crash. The C standard does not allow you to read the value of
>>>the pointer after you have freed it.
>>
>>Er ... no. Why would the contents of "ptr" be placed into an address
>>register? I would expect the address of "ptr" (i.e., &ptr) to be
>>loaded into an address register, and the contents of "ptr" to be
>>loaded into a data register.
>
>
> Why *wouldn't* the contents of "ptr" be placed into an address
> register?
>
> If you're going to assume characteristics that are common to most
> real-world implementations but aren't guaranteed by the standard, you
> might as well just save the value as a pointer:
>
> int *ptr = malloc(whatever);
> int *before = ptr;
> free(ptr);
> if (ptr == before) { /* warning: undefined behavior */
> printf("bits didn't change\n");
> }
> else {
> printf("bits changed\n");
> }
>
> Or, for that matter:
>
> printf("bits didn't change\n"); /* 8-)} */
>
> If you're going to avoid undefined behavior, there's not much point in
> going halfway. memcpy()ing the value to an array of unsigned char
> avoids UB; casting to unsigned long doesn't.
>
>
>>Also, you can read the contents of "ptr" after a call to free(), but
>>you cannot read the contents of the memory *pointed to* by "ptr".
>
>
> That's incorrect.
>
> In most real-world implementations, you can successfully read both the
> contents of ptr and the memory pointed to by ptr after a call to
> free(). It's undefined behavior, but most implementations don't do
> anything to make it fail. An address is an address, memory is memory,
> and you can still read it even if you no longer "own" it. (In some
> cases, if the memory is actually returned to the OS and removed from
> the program's visible memory space, a reference to the deallocated
> memory might actually trap; a reference to just the pointer value is
> less likely to do so.)
>
> But as far as the standard is concerned, attempting to refer to the
> allocated memory after the call to free() invokes undefined behavior
> (as you know) *and* the pointer value itself becomes indeterminate
> (even if the bits don't change), so any attempt to refer to that value
> will also invoke undefined behavior. Even this:
>
> free(ptr);
> if (ptr == NULL) { ... }
>
> or this:
>
> free(ptr);
> unsigned long foo = (unsigned long)ptr;
>
> invokes undefined behavior. It happens that the typical result of
> this undefined behavior is to read the value of ptr, but the standard
> allows nasal daemons.
>
> Why is it defined this way? Because, for example, a conforming
> implementation might implement any reference to a pointer value
> (including a comparison to NULL or a conversion to unsigned long) by
> loading the pointer value into an address register, and the act of
> loading the value might do a validity check, and trap if it's invalid.
> Such a trap is not required, of course, but the point is that the
> standard doesn't render such an implementation non-conforming.
>
> There could be other reasons why referring to the value of ptr might
> cause problems; the address register thing is just one possible
> example.
>
Thanks for the explanation; that was very clear and well presented.
And yet a nagging question keeps going around in my mind ... you
say that a construct of the form
unsigned long foo = (unsigned long)ptr;
can lead to UB (since the compiler may perform some interpretation
of ptr), and yet
unsigned char foo[4]; /* just making an assumption for this example */
memcpy(foo, &ptr, sizeof(ptr));
does _not_ invoke UB. Why not? Isn't the compiler here able
to perform the same interpretation of "ptr" as it did on the
cast to an unsigned long?
-- Ron Collins Air Defense/RTSC/BCS "I have a plan so cunning, you could put a tail on it and call it a weasel"
- Next message: RCollins: "Re: How to know the memory pointed by a ptr is freed?"
- Previous message: Mabden: "Re: Is it possible to get the caller's name in C ?"
- In reply to: Keith Thompson: "Re: How to know the memory pointed by a ptr is freed?"
- Next in thread: Keith Thompson: "Re: How to know the memory pointed by a ptr is freed?"
- Reply: Keith Thompson: "Re: How to know the memory pointed by a ptr is freed?"
- Reply: Martin Ambuhl: "Re: How to know the memory pointed by a ptr is freed?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|