By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,227 Members | 1,269 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,227 IT Pros & Developers. It's quick & easy.

free() question

P: n/a
I apologize if this is a stupid question. I was just curious... is
there any reason why free() doesn't set the pointer (that was passed to
it) to NULL after giving the memory back to the heap? I decided to
write a wrapper for free() to do just that, and I wondered why free()
itself didn't do it.

Aaron
--
/usr/bin/fortune says:
How can you work when the system's so crowded?

Nov 14 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Aaron Walker wrote:

I apologize if this is a stupid question. I was just curious... is
there any reason why free() doesn't set the pointer (that was passed to
it) to NULL after giving the memory back to the heap? I decided to
write a wrapper for free() to do just that, and I wondered why free()
itself didn't do it.

There are no stupid questions. As designed, free() receives a value, the
address of the allocation to be freed. It doesn't know where the value
came from. Consider..

int *arr, *tmp;
arr = malloc(N * sizeof *arr);
tmp = arr;

...Both arr and tmp hold the address of memory returned by malloc(). It
doesn't make any difference now whether I call..

free(arr);
or
free(tmp);

...because the free() function receives the address of the allocation and
no information about arr or tmp at all. It is not possible for free() to
set them to NULL.
--
Joe Wright http://www.jw-wright.com
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 14 '05 #2

P: n/a
Aaron Walker <ka*****@REMOVETHIScfl.rr.com> wrote in message news:<3P*********************@twister.tampabay.rr. com>...
I apologize if this is a stupid question. I was just curious... is
there any reason why free() doesn't set the pointer (that was passed to
it) to NULL after giving the memory back to the heap?


It's not a stupid question, but it *is* a FAQ (7.21)

If free() modified its argument like this it wouldn't be implementable
as a C function.

-thomas
Nov 14 '05 #3

P: n/a
Aaron Walker wrote:
I apologize if this is a stupid question. I was just curious... is
there any reason why free() doesn't set the pointer (that was passed to
it) to NULL after giving the memory back to the heap? I decided to
write a wrapper for free() to do just that, and I wondered why free()
itself didn't do it.

Aaron


Some of use don't believe this would be a particularly useful feature.
If the goal is to be able to test a pointer in order to determine
whether it still points to valid accessible memory, a test against NULL
is not sufficient. Consider:

int *p1 = malloc(5 * sizeof *p1);
int *p2 = p1;
magic_free_and_NULL(p1);

if (p1 != NULL) /* OK */
{
p1[0] = 1234;
}

if (p2 != NULL) /* BAM! Undefined. */
{
p2[1] = 4321; /* BAM! Undefined. */
}

In this example, it's not even safe to test p2, let alone dereference
it. (The value of a pointer to memory that has been freed is indeterminate.)

Also, consider this:

free(p - 1);

What should be set to NULL here?

Setting freed pointers to NULL is handy in some cases, but is not good
as a general technique for determining when memory has been freed.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #4

P: n/a
On Fri, 26 Dec 2003 14:44:15 GMT, Aaron Walker
<ka*****@REMOVETHIScfl.rr.com> wrote:
I apologize if this is a stupid question. I was just curious... is
there any reason why free() doesn't set the pointer (that was passed to
it) to NULL after giving the memory back to the heap? I decided to
write a wrapper for free() to do just that, and I wondered why free()
itself didn't do it.

free() does not receive the pointer. C passes arguments by value.
That means that free() receives a copy of the pointer (just its
value). How would you suggest that free() trace this value back to
the variable that contains it?

This question is asked here in various guises quite frequently and is
covered in the faq. The basic answer is that a function cannot affect
the variables that contain the calling arguments.
<<Remove the del for email>>
Nov 14 '05 #5

P: n/a
On Fri, 26 Dec 2003 16:48:38 +0000, Joe Wright wrote:
Aaron Walker wrote:

I apologize if this is a stupid question. I was just curious... is
there any reason why free() doesn't set the pointer (that was passed to
it) to NULL after giving the memory back to the heap? I decided to
write a wrapper for free() to do just that, and I wondered why free()
itself didn't do it.

There are no stupid questions. As designed, free() receives a value, the
address of the allocation to be freed. It doesn't know where the value
came from. Consider..

int *arr, *tmp;
arr = malloc(N * sizeof *arr);
tmp = arr;

..Both arr and tmp hold the address of memory returned by malloc(). It
doesn't make any difference now whether I call..

free(arr);
or
free(tmp);

..because the free() function receives the address of the allocation and
no information about arr or tmp at all. It is not possible for free() to
set them to NULL.


Exactly. And nothing more is necessary within the standard C library.
It would be trivial to implement one's own function which takes a handle
and sets the pointer to null, thus solving the problem without adding more
unnecessary cruft to the C library, as it appears the parent poster has
already done.

void nullfree ( void **blk )
{
free (*blk);
*blk = NULL;
}
Nov 14 '05 #6

P: n/a
in comp.lang.c i read:
nothing more is necessary within the standard C library.
necessary -- or unnecessary?
It would be trivial to implement one's own function which takes a handle
and sets the pointer to null, thus solving the problem without adding more
unnecessary cruft to the C library, as it appears the parent poster has
already done.

void nullfree ( void **blk )
{
free (*blk);
*blk = NULL;
}


that could only assign a null pointer to the variable whose address was
passed; what of any aliases? code sloppy enough to use a pointer after it
has been free'd probably has many aliases too, yet those are not handled,
so remain armed bombs. sometimes just clearing the one pointer is enough,
and so plenty of people do have a FREE(p) macro that expands to `do {
free(p); p=0; } while (0)'. but it takes some care to keep from falling
into the trap of complacency -- which a platform that makes it clear when a
null pointer is used, e.g., by stopping the program in a very visible way
-- can help reinforce, and if it becomes ingrained any aliases are nearly
certain to bite, though perhaps not right away.

--
a signature
Nov 14 '05 #7

P: n/a
Michael Baehr wrote:
It would be trivial to implement one's own function which takes a handle
and sets the pointer to null, thus solving the problem without adding more
unnecessary cruft to the C library, as it appears the parent poster has
already done.

void nullfree ( void **blk )
{
free (*blk);
*blk = NULL;
}


This is great if you happen to use void * a lot, but it is not guaranteed to
work for other kinds of pointer. For example:

int *p = malloc(n * sizeof *p);
if(p != NULL)
{
use(p, n);
nullfree(&p); /* undefined behaviour */
}

void * is a generic pointer type, but void ** is not.

You could do this:

int *p = malloc(n * sizeof *p);
if(p != NULL)
{
void *q = p;
use(p, n);
nullfree(&q);
}

but what's the point?

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #8

P: n/a
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
Michael Baehr wrote:
void nullfree ( void **blk )
{
free (*blk);
*blk = NULL;
}
This is great if you happen to use void * a lot, but it is not
guaranteed to work for other kinds of pointer. For example:

int *p = malloc(n * sizeof *p);
if(p != NULL)
{
use(p, n);
nullfree(&p); /* undefined behaviour */


Constraint violation, in fact. However even with the cast
nullfree((void **)&p) is still undefined behaviour.
}

void * is a generic pointer type, but void ** is not.


And the reason I know that is by reading C Unleashed and the
woes over the interface for a wrapper for realloc. :-)

--
Simon.
Nov 14 '05 #9

P: n/a
Simon Biber wrote:
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
Michael Baehr wrote:
> void nullfree ( void **blk )
> {
> free (*blk);
> *blk = NULL;
> }
This is great if you happen to use void * a lot, but it is not
guaranteed to work for other kinds of pointer. For example:

int *p = malloc(n * sizeof *p);
if(p != NULL)
{
use(p, n);
nullfree(&p); /* undefined behaviour */


Constraint violation, in fact.


Good Lord, so it is. Thanks.
However even with the cast
nullfree((void **)&p) is still undefined behaviour.
}

void * is a generic pointer type, but void ** is not.


And the reason I know that is by reading C Unleashed and the
woes over the interface for a wrapper for realloc. :-)


What goes around, comes around.

(Incidentally, even in the little monologue you describe, I managed to
introduce a common error - taking the address of an rvalue!)

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #10

P: n/a
"Simon Biber" <ne**@ralminNOSPAM.cc> wrote in message
news:3f***********************@news.syd.swiftdsl.c om.au...
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
Michael Baehr wrote:
void nullfree ( void **blk )
{
free (*blk);
*blk = NULL;
}
This is great if you happen to use void * a lot, but it is not
guaranteed to work for other kinds of pointer. For example:

int *p = malloc(n * sizeof *p);
if(p != NULL)
{
use(p, n);
nullfree(&p); /* undefined behaviour */


Constraint violation, in fact.


Yes, but curiously (it would seem) by 6.5.16.1p1 (assignment operators), not
by 6.5.2.2p1 (function calls).
However even with the cast
nullfree((void **)&p) is still undefined behaviour.


True, because the cast itself (or more precisely the conversion of &p, be it
explicit or implicit) potentially invokes undefined behaviour if the
resultant void** pointer is not properly aligned (6.3.2.3p5).

If the conversion _is_ aligned then the function call itself does not invoke
UB (by virtue of 6.3.2.3p5 and 6.5.16.1p2), although UB will occur at
evaluation of *blk in nullfree.
}


--
Peter
Nov 14 '05 #11

P: n/a
"Kevin Goodsell" <us*********************@neverbox.com> wrote in message
news:cV0Hb.20432
int *p1 = malloc(5 * sizeof *p1);
int *p2 = p1;
magic_free_and_NULL(p1);

if (p1 != NULL) /* OK */
{
p1[0] = 1234;
}

if (p2 != NULL) /* BAM! Undefined. */


I have a vague recollection about this being undefined, but I can't imagine
a case where it would fail.
Care to explain?
Nov 14 '05 #12

P: n/a
Servé Lau wrote:
"Kevin Goodsell" <us*********************@neverbox.com> wrote in message
news:cV0Hb.20432
int *p1 = malloc(5 * sizeof *p1);
int *p2 = p1;
magic_free_and_NULL(p1);

if (p1 != NULL) /* OK */
{
p1[0] = 1234;
}

if (p2 != NULL) /* BAM! Undefined. */

I have a vague recollection about this being undefined, but I can't imagine
a case where it would fail.
Care to explain?


It will probably behave as expected on almost all implementations. But
imagine a hypothetical system with special-purpose address registers and
protected memory. Loading an address into these registers causes the
validity of the address to be checked, and some kind of exception occurs
for an invalid address. Once the memory at some address has been freed,
that address is marked invalid, so loading that address into one of the
address registers would cause an exception.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.