Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > How to know the memory pointed by a ptr is freed?

Reply
Thread Tools

How to know the memory pointed by a ptr is freed?

 
 
Chris Torek
Guest
Posts: n/a
 
      08-18-2004
>Keith Thompson wrote:
>> ... but free could additionally be implemented as a macro:
>> #define free(p) __builtin_free(p)
>> which can do whatever compile-time magic is necessary to figure out
>> whether the argument is an object.


True enough; but there must be a function version as well:

void (*fp)(void *);
...
fp = input_value == 42 ? free : zorg;
fp(ptr);

In the end, it is "too difficult" (and pointless, if you will pardon
the wording ) for free() to change the bits stored in an object
passed to it.

In article <news:cfulvg$b0m$>
RCollins <> wrote:
>If anybody looks at the standard to learn how to call free(),
>they *should* be able to count on the value (i.e. the bit pattern)
>of "ptr" not changing. (Why they would want to, I can't say).


Here is the real problem -- the disconnect: the *bit pattern* and
the *value* are not the same thing!

Those who have written assembly code, or investigated thier C
implementations far enough, are already familiar with this with
respect to floating-point numbers. Typically "int" or "long"
is 4 or 8 bytes, and "float" or "double" is also 4 or 8 bytes
-- but a 4-byte "int" that represents (say) 12345 is *not*
also 12345.0f, not at all.

C99 makes it clear that there is a "representation" (as stored
in an object) for some particular value. The representation is
the bit-pattern in memory, and using "unsigned char *" pointers,
you can always inspect the representation of any addressable
object:

#include <stdio.h>

void show(const char *, void *, size_t);

int main(void) {
int i = 12345;
float f = 12345.0;

show("int i = 12345 ", &i, sizeof i);
show("float f = 12345.0", &f, sizeof f);
return 0;
}

void show(const char *prefix, void *mem, size_t len) {
size_t i;
unsigned char *cp = mem;

printf("%s:", prefix);
for (i = 0; i < len; i++)
printf(" %2.2x", (unsigned int)cp[i]);
printf("\n");
}

% cc -o t -O -ansi -pedantic -W -Wall t.c
% ./t
int i = 12345 : 39 30 00 00
float f = 12345.0: 00 e4 40 46
%

Now, the trick to free() is that, while it is virtually certain
not to change the bit pattern -- the *representation* of some value
-- what it *can* do is change the *meaning* of those bits. Just
as (in this case) the bits "39 30 00 00" "mean" 12345 when they
represent an int, we need a completely different set of bytes to
"mean" 12345.0 as a float. The free() function can, in effect,
change the way that a pointer is interpreted.

Imagine a system just like your typical 32-bit Intel, except that
pointers use *eight* bytes. Half the pointer is used as an index
into a table. When table[i] is set to 0, the pointer is considered
invalid, but when table[i] is set nonzero, the pointer is valid.
The free() function clears table[i] -- so now, even though the
"memory address" half of the pointer is still good, the pointer
itself is invalid.

The pointer is unchanged, but it has gone from "valid" to "invalid".
The *representation* is unchanged, but the *value* is different.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      08-18-2004
RCollins <> writes:
> Keith Thompson wrote:

[...]
> I dunno ... the standard shows the definition of free() as
> void free(void *ptr)
>
> If anybody looks at the standard to learn how to call free(),
> they *should* be able to count on the value (i.e. the bit pattern)
> of "ptr" not changing. (Why they would want to, I can't say).


The object ptr can be viewed in more than one way. After a call to
free, attempting to view it as a pointer value invokes undefined
behavior -- but you can still legally view it (as you can view any
object) as an array of unsigned char.

[...]
> Ummm... what do you mean by "indeterminate"?


An indeterminate value is either an unspecified value or a trap
representation. You'd have to follow the maze of twisty definitions
in section 3 of the standard to understand precisely what unspecified
values and trap representations are, but basically it means that using
the value can invoke undefined behavior.

A "value" is the "precise meaning of the contents of an object when
interpreted as having a specific type". So the value of ptr when
viewed as a pointer is different from the value of ptr when viewed as
an array of unsigned char -- though both values have the same
representation. (Very roughly, value == representation + type.)

> I can do a memcpy()
> of the bits in "p" to an array of unsigned char, and determine
> *exactly* what the value is (or, simpler yet, since I know that
> free() did not change "p", I can simply print it out before the
> call to free() ... it will be the same after the call).


memcpy() doesn't use the value of ptr *as a pointer*, so it doesn't
invoke undefined behavior.

> Or do we mean that I cannot 'see' the bits in "p" at all? That sounds
> like a trap representation to me ... and traps are very deterministic
> (there's only a limited number of them).


You can see the bits; you just can't see the pointer.

BTW, referring to a trap representation doesn't necessarily cause a
trap; undefined behavior can include behaving just as you'd expect it
to.

> Or do we mean that I shouldn't be 'touching' the memory returned to
> the system by free(), because we cannot determine the state of that
> memory after the free() call?


It's also the case that you shouldn't touch the memory to which ptr
had pointed before the call to free() -- but the interesting thing is
that you shouldn't touch the value of ptr itself, even if you don't
dereference it.

> > In my opinion, free(ptr) cannot legally change the value of ptr
> > (other
> > than causing it to become indeterminate), but only because a strictly
> > conforming program can tell the difference if it does (by copying the
> > value of ptr to an array of unsigned bytes before and after the free()
> > and comparing the values). Note that directly examining the value of
> > ptr itself isn't allowed after the call to free().

>
> I agree; I think the whole issue boils down to a very convoluted and
> complex warning about trying to access free()'d memory. (i.e., don't
> do it!)


Don't try to access free()'d memory *or* the value of the pointer that
pointed to it. The free()'d memory should be treated as if it no
longer exists; even an attempt to view it as an array of unsigned char
invokes undefined behavior. The pointer value is still there, sitting
in an object that you declared yourself, tempting you, begging you,
softly whispering "go ahead, access me, evaluate me, you know you're
curious, what could go wrong?", all the while getting the demons lined
up and ready to fly out your nose. (It's late; I *really* need to go
home.)

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
 
 
 
Ravi Uday
Guest
Posts: n/a
 
      08-18-2004

"Keith Thompson" <kst-> wrote in message
news:...
> RCollins <> writes:
> > Keith Thompson wrote:

> [...]
> > I dunno ... the standard shows the definition of free() as
> > void free(void *ptr)
> >
> > If anybody looks at the standard to learn how to call free(),
> > they *should* be able to count on the value (i.e. the bit pattern)
> > of "ptr" not changing. (Why they would want to, I can't say).

>
> The object ptr can be viewed in more than one way. After a call to
> free, attempting to view it as a pointer value invokes undefined
> behavior -- but you can still legally view it (as you can view any
> object) as an array of unsigned char.
>
> [...]
> > Ummm... what do you mean by "indeterminate"?

>
> An indeterminate value is either an unspecified value or a trap
> representation. You'd have to follow the maze of twisty definitions
> in section 3 of the standard to understand precisely what unspecified
> values and trap representations are, but basically it means that using
> the value can invoke undefined behavior.
>
> A "value" is the "precise meaning of the contents of an object when
> interpreted as having a specific type". So the value of ptr when
> viewed as a pointer is different from the value of ptr when viewed as
> an array of unsigned char -- though both values have the same
> representation. (Very roughly, value == representation + type.)
>
> > I can do a memcpy()
> > of the bits in "p" to an array of unsigned char, and determine
> > *exactly* what the value is (or, simpler yet, since I know that
> > free() did not change "p", I can simply print it out before the
> > call to free() ... it will be the same after the call).

>
> memcpy() doesn't use the value of ptr *as a pointer*, so it doesn't
> invoke undefined behavior.
>
> > Or do we mean that I cannot 'see' the bits in "p" at all? That sounds
> > like a trap representation to me ... and traps are very deterministic
> > (there's only a limited number of them).

>
> You can see the bits; you just can't see the pointer.
>

Thats what the OP wanted, to know whether the pointer is valid.
I think the system/OS can fill the first word in the header of a freed
block with some
bit pattern (0xdeadbeef) before returning the call (free()) to the user
So seeing the memory dump of the pointer might be of clue.

Of-course you shouldnt de-reference the pointer once the free() returns !

> BTW, referring to a trap representation doesn't necessarily cause a
> trap; undefined behavior can include behaving just as you'd expect it
> to.
>
> > Or do we mean that I shouldn't be 'touching' the memory returned to
> > the system by free(), because we cannot determine the state of that
> > memory after the free() call?

>
> It's also the case that you shouldn't touch the memory to which ptr
> had pointed before the call to free() -- but the interesting thing is
> that you shouldn't touch the value of ptr itself, even if you don't
> dereference it.
>
> > > In my opinion, free(ptr) cannot legally change the value of ptr
> > > (other
> > > than causing it to become indeterminate), but only because a strictly
> > > conforming program can tell the difference if it does (by copying the
> > > value of ptr to an array of unsigned bytes before and after the free()
> > > and comparing the values). Note that directly examining the value of
> > > ptr itself isn't allowed after the call to free().

> >
> > I agree; I think the whole issue boils down to a very convoluted and
> > complex warning about trying to access free()'d memory. (i.e., don't
> > do it!)

>
> Don't try to access free()'d memory *or* the value of the pointer that
> pointed to it. The free()'d memory should be treated as if it no
> longer exists; even an attempt to view it as an array of unsigned char
> invokes undefined behavior. The pointer value is still there, sitting
> in an object that you declared yourself, tempting you, begging you,
> softly whispering "go ahead, access me, evaluate me, you know you're
> curious, what could go wrong?", all the while getting the demons lined
> up and ready to fly out your nose. (It's late; I *really* need to go
> home.)
>
> --
> Keith Thompson (The_Other_Keith) kst-

<http://www.ghoti.net/~kst>
> San Diego Supercomputer Center <*>

<http://users.sdsc.edu/~kst>
> We must do something. This is something. Therefore, we must do this.



 
Reply With Quote
 
Jens.Toerring@physik.fu-berlin.de
Guest
Posts: n/a
 
      08-19-2004
RCollins <> wrote:


> Jack Klein wrote:


>> On Tue, 17 Aug 2004 16:38:17 -0700, RCollins
>> <> wrote in comp.lang.c:
>>


> <snip>


>>>
>>>Which would /imply/ that free() can change the value of "ptr".

>>
>>
>> And what about the 37 copies made of that pointer after it was
>> returned from malloc() and passed to free()?
>>
>> Or what about the suitably sized array of unsigned chars into which
>> the bit pattern of the pointer was copied by memcpy()?


> I don't know ... the standard doesn't mention them. All I know is that
> the prototype for free() doesn't _appear_ to allow the value of "ptr"
> to be changed. (Ignoring the possibility of behind-the-scenes
> 'compiler magic'). As for those 37 copies ... I'd say it was up to
> the programmer to keep them straightened out properly.


>>
>> The reason the term 'indeterminate' is used in this context is that
>> the standard makes any use of an 'indeterminate' value (other than
>> with an lvalue type other than unsigned char) undefined behavior.


> While in a practical sense we all know what it means (or we should,
> if we're going to make a living at this stuff), in another sense it
> is somewhat ambiguous. After a call to free(), the value of "ptr"
> is indeterminate. Does that mean that there is now a random bit
> pattern stored in "ptr", or does it mean that we cannot under any
> circumstances 'view' the bit pattern stored in "ptr"?


> Of course, in the 'real world', it means neither. It simply means
> that we gave that memory back to the system and any access to it
> leads to undefined behavior.


>>
>> Consider a platform like today's common desktop, with memory
>> management hardware. Freeing a pointer might cause the block of
>> virtual memory that mapped to it to be removed from the program's
>> address space. Attempting to dereference the pointer, or even compare
>> it with NULL, could trigger an exception when it is loaded into an
>> addressing register. That's a pretty good example of undefined
>> behavior.


> Does this mean I can't copy out the bit pattern and view it?
> (say, with a memcpy() into an array of unsigned chars). While
> a bit pattern representing a trap may have been copied into "ptr",
> I don't think free is _allowed_ to do that.


> Here is the question it all boils down to:


> Given that the standard specifies the prototype of free() to be
> void free(void *ptr)


> Is then free() *required* to behave that way? By the definition,
> the bit pattern of "ptr" should not change; but is 'compiler magic'
> allowed to happen here with a prototype that doesn't explicitly
> *show* the value has changed?


I think it's not so much "compiler magic" but a question how the
underlying hardware works. Let's assume you have a machine that
has dedicated address registers (like e.g. the 68000 processors
had). Moreover, the OS is allowed to unmap the address from the
virual address space of a process once free() has called on a
pointer. If now the processor also tests if an address it loads
into an address register is mapped into the address space of the
process (with an exception for an address that represents the NULL
pointer) and e.g. segfaults when it isn't than you have a sitation
where none of the bits of the pointer ever changed but taking its
value (by loading it into an address register) isn't possible.

If memcpy()ing the content of that pointer somehwere else is
possible may depend on such a machine on what kind of machine
instructions are used in the process - if the value of the pointer
gets copied into an address register in the process it would
crash the program, if it's going in a data register (or no
register at all) it might work perfectly well.

While no machine is required to work that way it's possible to
write a conforming C compiler such a kind of machine. But
therefore you need some allowance in the standard that says
that "the result taking the value of a free()ed pointer is
indeterminate". Also a lot of other seemingly hard to explain
requirements (like, for example, why, when you have an array
a[10], calculating a+20 is undefined) suddenly make a lot of
sense on such a machine.
Regards, Jens
--
\ Jens Thoms Toerring ___
\__________________________ http://www.toerring.de
 
Reply With Quote
 
RCollins
Guest
Posts: n/a
 
      08-19-2004


wrote:
> RCollins <> wrote:
>
>
>
>>Jack Klein wrote:

>
>
>>>On Tue, 17 Aug 2004 16:38:17 -0700, RCollins
>>><> wrote in comp.lang.c:
>>>

>
>
>><snip>

>
>
>>>>Which would /imply/ that free() can change the value of "ptr".
>>>
>>>
>>>And what about the 37 copies made of that pointer after it was
>>>returned from malloc() and passed to free()?
>>>
>>>Or what about the suitably sized array of unsigned chars into which
>>>the bit pattern of the pointer was copied by memcpy()?

>
>
>>I don't know ... the standard doesn't mention them. All I know is that
>>the prototype for free() doesn't _appear_ to allow the value of "ptr"
>>to be changed. (Ignoring the possibility of behind-the-scenes
>>'compiler magic'). As for those 37 copies ... I'd say it was up to
>>the programmer to keep them straightened out properly.

>
>
>>>The reason the term 'indeterminate' is used in this context is that
>>>the standard makes any use of an 'indeterminate' value (other than
>>>with an lvalue type other than unsigned char) undefined behavior.

>
>
>>While in a practical sense we all know what it means (or we should,
>>if we're going to make a living at this stuff), in another sense it
>>is somewhat ambiguous. After a call to free(), the value of "ptr"
>>is indeterminate. Does that mean that there is now a random bit
>>pattern stored in "ptr", or does it mean that we cannot under any
>>circumstances 'view' the bit pattern stored in "ptr"?

>
>
>>Of course, in the 'real world', it means neither. It simply means
>>that we gave that memory back to the system and any access to it
>>leads to undefined behavior.

>
>
>>>Consider a platform like today's common desktop, with memory
>>>management hardware. Freeing a pointer might cause the block of
>>>virtual memory that mapped to it to be removed from the program's
>>>address space. Attempting to dereference the pointer, or even compare
>>>it with NULL, could trigger an exception when it is loaded into an
>>>addressing register. That's a pretty good example of undefined
>>>behavior.

>
>
>>Does this mean I can't copy out the bit pattern and view it?
>>(say, with a memcpy() into an array of unsigned chars). While
>>a bit pattern representing a trap may have been copied into "ptr",
>>I don't think free is _allowed_ to do that.

>
>
>>Here is the question it all boils down to:

>
>
>>Given that the standard specifies the prototype of free() to be
>>void free(void *ptr)

>
>
>>Is then free() *required* to behave that way? By the definition,
>>the bit pattern of "ptr" should not change; but is 'compiler magic'
>>allowed to happen here with a prototype that doesn't explicitly
>>*show* the value has changed?

>
>
> I think it's not so much "compiler magic" but a question how the
> underlying hardware works. Let's assume you have a machine that
> has dedicated address registers (like e.g. the 68000 processors
> had). Moreover, the OS is allowed to unmap the address from the
> virual address space of a process once free() has called on a
> pointer. If now the processor also tests if an address it loads
> into an address register is mapped into the address space of the
> process (with an exception for an address that represents the NULL
> pointer) and e.g. segfaults when it isn't than you have a sitation
> where none of the bits of the pointer ever changed but taking its
> value (by loading it into an address register) isn't possible.


No, this is too deep. Given the standard's definition of free(),
then I should be able to do this:

#include <stdio.h>

int mail(void) {
unsigned long before, after;
int *ptr;

ptr = malloc(100); /* ignore possible errors for now */
before = (unsigned long) ptr;
free(ptr);
after = (unsigned long) ptr;

if (before == after) printf("bits in ptr have not changed\n")
else printf("bits in ptr HAVE changed\n");

return 0;
}

And I should see that the bit representation in "ptr" have not
changed. Regardless of whether they point to a valid memory
location or not.


>
> If memcpy()ing the content of that pointer somehwere else is
> possible may depend on such a machine on what kind of machine
> instructions are used in the process - if the value of the pointer
> gets copied into an address register in the process it would
> crash the program, if it's going in a data register (or no
> register at all) it might work perfectly well.


Copying the (bits) contents of "ptr" to another location should
*always* be allowed; copying them back into "ptr" is another
question.

>
> While no machine is required to work that way it's possible to
> write a conforming C compiler such a kind of machine. But
> therefore you need some allowance in the standard that says
> that "the result taking the value of a free()ed pointer is
> indeterminate". Also a lot of other seemingly hard to explain
> requirements (like, for example, why, when you have an array
> a[10], calculating a+20 is undefined) suddenly make a lot of
> sense on such a machine.
> Regards, Jens


Keep in mind the OP's original question: is there any way to know
if the bit representation in "ptr" is a valid memory location?

--
Ron Collins
Air Defense/RTSC/BCS
"I have a plan so cunning, you could put a tail on it and call it a weasel"

 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      08-19-2004
On Thu, 19 Aug 2004 08:19:51 -0700
RCollins <> wrote:

> wrote:
> > RCollins <> wrote:
> >
> >
> >
> >>Jack Klein wrote:

> >
> >
> >>>On Tue, 17 Aug 2004 16:38:17 -0700, RCollins
> >>><> wrote in comp.lang.c:


<snip freed pointers>

> No, this is too deep. Given the standard's definition of free(),
> then I should be able to do this:
>
> #include <stdio.h>
>
> int mail(void) {
> unsigned long before, after;
> int *ptr;
>
> ptr = malloc(100); /* ignore possible errors for now */


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.

On some REAL implementations thus would cause your program to fail.

> before = (unsigned long) ptr;


Implementation defined behaviour. A pointer might require more bits than
a long.

> free(ptr);
> after = (unsigned long) ptr;


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.

> if (before == after) printf("bits in ptr have not changed\n")
> else printf("bits in ptr HAVE changed\n");
>
> return 0;
> }
>
> And I should see that the bit representation in "ptr" have not
> changed. Regardless of whether they point to a valid memory
> location or not.


The code you wanted was something like:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
int *ptr;
unsigned char before[sizeof ptr];

ptr = malloc(100); /* ignore possible errors for now */
memcpy( before, ptr, sizeof ptr );
free(ptr);

if (memcmp( before, ptr, sizeof ptr) == 0)
printf("bits in ptr have not changed\n")
else
printf("bits in ptr HAVE changed\n");
return 0;
}


> > If memcpy()ing the content of that pointer somehwere else is
> > possible may depend on such a machine on what kind of machine
> > instructions are used in the process - if the value of the pointer
> > gets copied into an address register in the process it would
> > crash the program, if it's going in a data register (or no
> > register at all) it might work perfectly well.

>
> Copying the (bits) contents of "ptr" to another location should
> *always* be allowed; copying them back into "ptr" is another
> question.


Copying the bits is allowed, but casting a pointer to an unsigned long
does not copy the bits it takes the value and applies an implementation
defined translation. If you want to copy bits use memcpy as I did and
copy them in to a large enough array of unsigned char as unsigned char
is guaranteed by the standard to not have any trap values.

> > While no machine is required to work that way it's possible to
> > write a conforming C compiler such a kind of machine. But
> > therefore you need some allowance in the standard that says
> > that "the result taking the value of a free()ed pointer is
> > indeterminate". Also a lot of other seemingly hard to explain
> > requirements (like, for example, why, when you have an array
> > a[10], calculating a+20 is undefined) suddenly make a lot of
> > sense on such a machine.
> > Regards, Jens

>
> Keep in mind the OP's original question: is there any way to know
> if the bit representation in "ptr" is a valid memory location?


There is no standard way to find out. The only value that you cannot
dereference that you can portably detect is the null pointer.
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      08-19-2004
Flash Gordon wrote:
>
> On Thu, 19 Aug 2004 08:19:51 -0700
> RCollins <> wrote:


> > ptr = malloc(100); /* ignore possible errors for now */

>
> 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.



Kind of depends on the compiler. C99 would require this, yes, but not
C89.



Brian Rodenborn
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-19-2004
writes:
[snip]
> I think it's not so much "compiler magic" but a question how the
> underlying hardware works.

[snip]

After free(ptr), the value of ptr becomes indeterminate. That doesn't
require any "compiler magic", since it can become indeterminate
without any change in the bits.

A change in the bits that constitute the representatin of ptr would
require "compiler magic" (and would be of questionable legality).

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      08-19-2004
On Thu, 19 Aug 2004 18:18:36 GMT
Default User <> wrote:

> Flash Gordon wrote:
> >
> > On Thu, 19 Aug 2004 08:19:51 -0700
> > RCollins <> wrote:

>
> > > ptr = malloc(100); /* ignore possible errors for now */

> >
> > 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.

>
> Kind of depends on the compiler. C99 would require this, yes, but not
> C89.


No cast so as I understand it the compiler is required to raise a
diagnostic for assigning an integer (which it assumes malloc returns in
the absence of of a definition) to a pointer. One reason people around
here recommend against casting the return value of malloc
--
Flash Gordon
Sometimes I think shooting would be far too good for some people.
Although my email address says spam, it is real and I read it.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-19-2004
RCollins <> writes:
[...]
> No, this is too deep. Given the standard's definition of free(),
> then I should be able to do this:
>
> #include <stdio.h>
>
> int mail(void) {
> unsigned long before, after;
> int *ptr;
>
> ptr = malloc(100); /* ignore possible errors for now */
> before = (unsigned long) ptr;
> free(ptr);
> after = (unsigned long) ptr;
>
> if (before == after) printf("bits in ptr have not changed\n")
> else printf("bits in ptr HAVE changed\n");
>
> return 0;
> }


ITYM "main", not "mail" (though of course a function called "mail" is
perfectly valid). And you're probably assuming that an int* will fit
into an unsigned long, which isn't guaranteed.

After the call to free(), the value if ptr is indeterminate. Any
reference to that value, even to convert it to unsigned long, causes
undefined behavior. On most or all real-world systems, the converson
just copies the bits, but it could, for example, load the pointer
value into an address register and trap if the pointer value is
invalid.

Here's my version of your program. Since refers to the representation
of ptr, not to its value as a pointer, it doesn't invoke undefined
behavior.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int *ptr;
unsigned char *before;
unsigned char *after;

/*
* We assume for now that all malloc() calls are successful.
*/
ptr = malloc(sizeof *ptr);
before = malloc(sizeof ptr);
memcpy(before, &ptr, sizeof ptr);
free(ptr);
after = malloc(sizeof ptr);
memcpy(after, &ptr, sizeof ptr);

if (memcmp(before, after, sizeof ptr) == 0) {
printf("bits in ptr have not changed\n");
}
else {
printf("bits in ptr have changed\n");
}
free(before);
free(after);

return 0;
}

This program (assuming all the malloc()s succeed) can print "bits in
ptr have changed" only if there's some compiler magic asociated with
the free() call that fiddles with ptr, even though the free() function
has no way within the language to know where ptr is, or even that the
argument was an object reference.

In my opinion, a conforming compiler cannot perform such magic. It's
not covered by the "as-if" rule because a program can detect it. A
*reasonable* program cannot detect it, and I wouldn't complain if the
standard were amended to allow this particular magic, but I don't
think that's going to happen.

> Keep in mind the OP's original question: is there any way to know
> if the bit representation in "ptr" is a valid memory location?


And the answer is: no, there's no portable way to do that. There may
be non-portable ways to do it, but only by depending on detailed
knowledge of the implementation (which could easily change with the
next release of the system).

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Need to know the size of the memory block pointed to by a char* Frodo Baggins C Programming 12 01-03-2007 12:19 PM
const ptr to const ptr ? franco ziade C Programming 3 02-17-2005 04:30 AM
How to convert a double **ptr in a double const ** const ptr? Heiko Vogel C Programming 3 09-14-2004 10:23 AM
what's the difference between delete ptr and ptr=0 -dont they accomplish the same Sid C++ 5 07-29-2004 03:42 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57