Value of ptr after free

6 views
Skip to first unread message

Vara prasad Kilari

unread,
Dec 6, 1994, 4:46:56 PM12/6/94
to
[ Article crossposted from comp.unix.programmer ]
[ Author was Vara prasad Kilari ]
[ Posted on 6 Dec 1994 19:39:47 GMT ]

Hi Everybody,

When free is called on a ptr variable (which was previously assigned the
return value from a malloc), would the ptr value (the address) is still the
same as before or it is made NULL ( 0 ) once the call to free returns.

I think, I saw some some compilers (Turbo C if I remember right) which make
the ptr (the address) to NULL, but now I use a Sun-OS compiler, and the ptr
has the same value as before the free call.

Is there a any standard, as to what the value should be.

I would prefer the NULL, because, now you know that, the ptr is freed. Otherwise
there may be chances of trying to free the same ptr more than once.

Thankx

Prasad

pra...@ug.eds.com

Edward L. Karrels

unread,
Dec 6, 1994, 6:26:37 PM12/6/94
to
In article <3c2m4g$2...@huron.eel.ufl.edu> pra...@netsun.mdc.com (Vara prasad Kilari) writes:

When free is called on a ptr variable (which was previously assigned the
return value from a malloc), would the ptr value (the address) is still the
same as before or it is made NULL ( 0 ) once the call to free returns.

I think, I saw some some compilers (Turbo C if I remember right) which make
the ptr (the address) to NULL, but now I use a Sun-OS compiler, and the ptr
has the same value as before the free call.

Is there a any standard, as to what the value should be.

I would prefer the NULL, because, now you know that, the ptr is freed.
Otherwise there may be chances of trying to free the same ptr more
than once.

For all C compilers, free() should not be able to change the value
of its argument. In C, all arguments are passed by value, so free()
only receives a copy of the pointer you give it. It can change that
copy, but it cannot touch your variable. It is a good idea to set
the variable to NULL yourself, though.

BTW, a function can change the value of one of your variables,
but it must be given a pointer to that variable.

change_this( &i );

--
Ed Karrels
kar...@mcs.anl.gov

It's not a 'black and white' monitor, it's just 'chromaticaly challenged'.

Jeff Obik Epler

unread,
Dec 6, 1994, 9:35:26 PM12/6/94
to
pra...@netsun.mdc.com (Vara prasad Kilari) writes:

>Hi Everybody,

>When free is called on a ptr variable (which was previously assigned the
>return value from a malloc), would the ptr value (the address) is still the
>same as before or it is made NULL ( 0 ) once the call to free returns.

Unless there's something weird about your compiler (or maybe
includes?), it will still hold the same value.

The reason is that, just like any other function, the parameter is
passed by value. The function can't modify it. (But it can modify
what it points to)

>I think, I saw some some compilers (Turbo C if I remember right) which make
>the ptr (the address) to NULL, but now I use a Sun-OS compiler, and the ptr
>has the same value as before the free call.

It might make a nice debugging tool to have this happen.. But I don't
think I've ever used a compiler that did this.

>Is there a any standard, as to what the value should be.

Yes, because of what I stated above.

>I would prefer the NULL, because, now you know that, the ptr is freed. Otherwise
>there may be chances of trying to free the same ptr more than once.

Try this:
void *__some_hidden_name;
#define FREE_AND_SET_NULL(x) (__some_hidden_name=(x),x=NULL,free(__some_hidden_name)

.. It will work if the 'x' is an lvalue and some pointer type, and
you'll get whatever the return value from free was.

>Thankx

>Prasad

>pra...@ug.eds.com

Jeff
--
____ "Always modulate your shield frequency" -- Me, after seeing Generations
\BI/ "And if I smile, please tell me some bad news
\/ before I laugh, and act like a fool" -The Who "Behind Blue Eyes"
grep -vi obik Running Linux 1.1 -- Free Unix for 386+ machines

John Bickers

unread,
Dec 6, 1994, 9:43:53 PM12/6/94
to
Quoted from <3c2m4g$2...@huron.eel.ufl.edu> by pra...@netsun.mdc.com (Vara prasad Kilari):

> When free is called on a ptr variable (which was previously assigned the
> return value from a malloc), would the ptr value (the address) is still the
> same as before or it is made NULL ( 0 ) once the call to free returns.

It is the same as before. If you were to think about how free() is
called, you might notice that it has no way to change the value of
the pointer, because it is only given the pointer's value, NOT its
address.

I don't think that any C compiler worth its salt would reset the
pointer to NULL. Doing so would take much more effort than not
doing so, and essentially requires the compiler to make "free"
some sort of special keyword.

> I would prefer the NULL, because, now you know that, the ptr is freed. Otherwise
> there may be chances of trying to free the same ptr more than once.

I think you'll find that there is no chance of trying to free the
same pointer more than once unless the code is buggy. Setting the
pointer value to NULL won't fix buggy code. However, the following
is sometimes used in cleanup routines...

if (pMem) {
free(pMem);
pMem = NULL;
}

when the programmer can't be sure that the cleanup routine will
only be called once.

> Prasad
--
*** John Bickers, TAP. jbic...@templar.actrix.gen.nz ***
*** Count Templar, ELITE, Cobra Mk III (FM-287) ***

Joe Foster of Borg

unread,
Dec 6, 1994, 10:21:16 PM12/6/94
to
In article <3c2m4g$2...@huron.eel.ufl.edu>, pra...@netsun.mdc.com (Vara prasad Kilari) writes:

[free(x) sets x to NULL on some compilers?]

> Is there a any standard, as to what the value should be.

> I would prefer the NULL, because, now you know that, the ptr is freed. Otherwise
> there may be chances of trying to free the same ptr more than once.

> Thankx

> Prasad

> pra...@ug.eds.com

Feel free to #define FREE(x) ((void)(free(x), x = 0))

--
Joe Foster (j...@bftsi0.UUCP or joe%bftsi...@uunet.uu.net)
Systems Mangler/Head Geek/Top Jolt Addict, BFTSI
WARNING: I cannot be held responsible for the above They're coming to
because my cats have apparently learned to type. take me away, ha ha!

Miguel Carrasquer

unread,
Dec 6, 1994, 6:22:09 PM12/6/94
to
In article <3c2m4g$2...@huron.eel.ufl.edu>,

Vara prasad Kilari <pra...@netsun.mdc.com> wrote:
>[ Article crossposted from comp.unix.programmer ]
>[ Author was Vara prasad Kilari ]
>[ Posted on 6 Dec 1994 19:39:47 GMT ]
>
>Hi Everybody,
>
>When free is called on a ptr variable (which was previously assigned the
>return value from a malloc), would the ptr value (the address) is still the
>same as before or it is made NULL ( 0 ) once the call to free returns.
>
>I think, I saw some some compilers (Turbo C if I remember right) which make
>the ptr (the address) to NULL, but now I use a Sun-OS compiler, and the ptr
>has the same value as before the free call.

That's impossible. All free() gets is a copy of the pointer:
if it's set to NULL in the free() function, that doesn't change
the value at the point where free() is called. If you want that,
you should pass the *address* of your pointer, like:

pfree(char **p)
{
free(*p);
*p=NULL;
}

call as: pfree(&p);

--
Miguel Carrasquer ____________________ ~~~
Amsterdam [ ||]~
m...@inter.NL.net ce .sig n'est pas une .cig

Peter Seebach

unread,
Dec 7, 1994, 2:41:48 PM12/7/94
to
In article <3c371e$5...@crcnis3.unl.edu> jep...@herbie.unl.edu (Jeff "Obik" Epler) writes:
>Try this:
>void *__some_hidden_name;
>#define FREE_AND_SET_NULL(x) (__some_hidden_name=(x),x=NULL,free(__some_hidden_name)

>.. It will work if the 'x' is an lvalue and some pointer type, and
>you'll get whatever the return value from free was.

... But it will do Bad Things if x has side-effects.

FREE_AND_SET_NULL(*p++); fails horribly.

(Assuming that p is a ptr-to-ptr...)

>Jeff


>grep -vi obik Running Linux 1.1 -- Free Unix for 386+ machines

-seebs
--
Peter Seebach - se...@solutions.solon.com -- se...@intran.xerox.com
C/Unix proto-wizard -- C/Unix questions? Send mail for help.

Mark Klenk

unread,
Dec 7, 1994, 2:49:59 PM12/7/94
to
Jeff "Obik" Epler wrote:
>
>Try this:
>void *__some_hidden_name;
>#define FREE_AND_SET_NULL(x) (__some_hidden_name=(x),x=NULL,free(__some_hidden_name)
>
>... It will work if the 'x' is an lvalue and some pointer type, and

>you'll get whatever the return value from free was.

Why make it so complicated? What good is the intermediate
assignment for?

I much prefer an earlier poster's suggestion of:

#define FREE(ptr) \
free(ptr); ptr = NULL

As long as you consistently use this, it will catch a lot
of problems.

---

mkl...@impact.xerox.com (Mark Klenk)

M. J. Saltzman

unread,
Dec 7, 1994, 4:36:12 PM12/7/94
to
mkl...@impact.xerox.com (Mark Klenk) writes:
> I much prefer an earlier poster's suggestion of:

>#define FREE(ptr) \
> free(ptr); ptr = NULL

This particular solution contains several booby traps that might catch
the unwary programmer (if not the macro's author, then the next
programmer that tries to use it).

First of all, one should enclose the names of macro parameters in
parentheses to make sure that operations in an expression argument
are grouped properly:

#define FREE(ptr) free(ptr); (ptr) = NULL

Second, one really needs to make sure that macros consisting of several
statements are built so that the statements group properly. Otherwise:

if ( done_with_what_it_points_to(ptr) )
FREE(ptr); /* oops! */

My personal favorite way to group statements in a macro is like this:

#define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0)

or

#define FREE(ptr) if (1) { free(ptr); (ptr) = NULL; } else

Then the sample call above works fine:

if ( done_with_what_it_points_to(ptr) )
FREE(ptr); /* OK now! */

In this particular case, all the statements are expressions, so we
could even make the macro an expression itself:

#define FREE(ptr) (free(ptr), (void) (ptr) = NULL)

The sample call also works with this method.

Finally, one needs to be aware that the argument occurs twice in the
macro, so it will be expanded twice, and side effects of evaluating
the argument will occur twice. In this example, there is no way
around that, so the programmer using the macro needs to be aware of
it. (The version with the hidden global variable was probably an
attempt to avoid this problem, but it doesn't work.)

On the other hand, I don't see a portable way to accomplish the task
in a function. The obvious attempt would look like this:

void my_free(void **ptr) { free(*ptr), *ptr = NULL; }

But wait! Should that argument really be a (void **)? What if I want
to free an array of ints? On some machines, the representation of an
(int *) may not be the same as that of a (void *), so when *ptr is
evaluated or stored into, its contents may be interpreted incorrectly.

So there is no perfect way to accomplish nulling pointers after
freeing their targets. I'd personally opt for one of the more
"bulletproof" macros.
--
Matthew Saltzman
Clemson University Math Sciences
m...@clemson.edu

Lawrence Kirby

unread,
Dec 7, 1994, 5:41:58 PM12/7/94
to
In article <3c2m4g$2...@huron.eel.ufl.edu>

pra...@netsun.mdc.com "Vara prasad Kilari" writes:

>[ Article crossposted from comp.unix.programmer ]
>[ Author was Vara prasad Kilari ]
>[ Posted on 6 Dec 1994 19:39:47 GMT ]
>
>Hi Everybody,
>
>When free is called on a ptr variable (which was previously assigned the
>return value from a malloc), would the ptr value (the address) is still the
>same as before or it is made NULL ( 0 ) once the call to free returns.
>
>I think, I saw some some compilers (Turbo C if I remember right) which make
>the ptr (the address) to NULL, but now I use a Sun-OS compiler, and the ptr
>has the same value as before the free call.
>
>Is there a any standard, as to what the value should be.

free() is just a function in C (albeit one in the standard library). *ALL*
function arguments in C are passed by value which means that the called
function works on a copy of the argument and cannot modify the original
(consider that you could provide an expression i.e. not a modifiable l-value
as the argument).

>I would prefer the NULL, because, now you know that, the ptr is freed.
> Otherwise
>there may be chances of trying to free the same ptr more than once.

If you want the pointer set to NULL after a call to free(), set it explicitly
in your code.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------

Graham Stoney

unread,
Dec 8, 1994, 11:33:29 PM12/8/94
to
fr...@genesis.demon.co.uk (Lawrence Kirby) writes:
>free() is just a function in C (albeit one in the standard library). *ALL*
>function arguments in C are passed by value which means that the called
>function works on a copy of the argument and cannot modify the original
>(consider that you could provide an expression i.e. not a modifiable l-value
>as the argument).

But we're dealing with a pointer here which previously pointed to something
meaningful, and no longer does so. According to the standard, the value of
such a pointer is indeterminate:

7.10.3 Memory management functions
...
The value of a pointer that refers to freed space is indeterminate.


So it is legal for the value of a pointer to change when it is passed to free,
and this could conceivably happen on a machine with unconventional hardware
which encoded unusual information in the pointer values.

>If you want the pointer set to NULL after a call to free(), set it explicitly
>in your code.

This is certainly true, however; it would be legal to build a machine that did
this for you, but it would be exceedingly unusual.

regards,
Graham

Neil Gall

unread,
Dec 9, 1994, 6:40:30 AM12/9/94
to
Vara prasad Kilari (pra...@netsun.mdc.com) says:

> When free is called on a ptr variable (which was previously assigned the
> return value from a malloc), would the ptr value (the address) is still the
> same as before or it is made NULL ( 0 ) once the call to free returns.

free() can't change the value of the pointer, as function
parameters are *always* passed by value in C. So it is guaranteed
that the pointer will have the same value after the call to free.
It's not very wise to use this value afterwards, however.

You could define your own free function which takes a pointer to
a pointer, and automatically clears the old pointer, thus:

void FreeMemory(void** ptr)
{
assert( ptr != NULL && *ptr != NULL );

free(*ptr);
*ptr = NULL;
}

--
| Neil Gall | Internet: ne...@hpsqf.sqf.hp.com |
| Hewlett-Packard Ltd | Phone: +44 (0)131 331 7112 |
| Queensferry Telecomms Operation | Fax: +44 (0)131 331 7488 |
| South Queensferry, Scotland | HP Telnet: 313-2112 |

Frederic STARK

unread,
Dec 12, 1994, 5:41:54 AM12/12/94
to
In article <mjs.786836172@hubcap> m...@hubcap.clemson.edu (M. J. Saltzman)
writes:

> My personal favorite way to group statements in a macro is like this:
>
> #define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0)

Which is my favorite too

> or
>
> #define FREE(ptr) if (1) { free(ptr); (ptr) = NULL; } else
>

Personal opinion: I just hate this one:
FREE(p)
printf( "Never reached\n" );
/* Well, sure, the compiler would warn you... */

> So there is no perfect way to accomplish nulling pointers after
> freeing their targets. I'd personally opt for one of the more
> "bulletproof" macros.

I remember a poster (but not his name, sorry), some weeks ago, that
suggested to add a 'assign and return old value' operator to C. He called
it ':='. With it, it seems that the FREE macro would be implementable:

#define FREE(ptr) free( (ptr):=NULL )

As soon as I'll have finished my time-travel-machine, I'll go back to the
70's and tell it to D.Ritchie..;-)

---------------------------------------------------------------------
Frederic STARK f...@comdev.fdn.fr NeXTMail OK (if small)
"No keyboard, press F1 to continue"
---------------------------------------------------------------------

Scott Burkett (cis)

unread,
Dec 13, 1994, 8:22:45 AM12/13/94
to
: When free is called on a ptr variable (which was previously assigned the

: return value from a malloc), would the ptr value (the address) is still the
: same as before or it is made NULL ( 0 ) once the call to free returns.

: I think, I saw some some compilers (Turbo C if I remember right) which make
: the ptr (the address) to NULL, but now I use a Sun-OS compiler, and the ptr
: has the same value as before the free call.

: Is there a any standard, as to what the value should be.

We aren't guaranteed anything as to the value of a free'd pointer. If a
given compiler explitcly sets the pointer to NULL, consider it an unportable
added bonus.

In your description of SunOS, the pointer (after free) points to a section
of memory which is not managed by the malloc/free package (other than the
fact that it resides below the break value).

+-------------------------------+-------------------------------------+
| Scott Burkett | "Beneath the noble bird, |
| ComputerPeople, Inc. | Between the proudest words, |
| St. Petersburg, FL, USA | Behind the beauty, cracks appear." |
+-------------------------------+-------------------------------------+

Gordon Burditt

unread,
Dec 15, 1994, 5:05:27 PM12/15/94
to
>When free is called on a ptr variable (which was previously assigned the
>return value from a malloc), would the ptr value (the address) is still the
>same as before or it is made NULL ( 0 ) once the call to free returns.

The value of the pointer is unchanged. C uses pass-by-value. A call
like:
func(foo);

where foo is a pointer, arithmetic type, or structure (but not an array)
cannot change the value of foo because foo is an argument to func.
(It might be changed for other reasons, like foo being a global variable
explicitly referenced in func.) If you want to change the interface
and make the call look like:

func(&foo);

now you can alter foo. But that's not the way free() is supposed to work.

>I think, I saw some some compilers (Turbo C if I remember right) which make
>the ptr (the address) to NULL,

If correct, this violates the ANSI C standard.

>but now I use a Sun-OS compiler, and the ptr
>has the same value as before the free call.

This is the way it is supposed to work. Why are you still
looking at the value of the pointer after the memory it
points to has been freed?

>I would prefer the NULL, because, now you know that, the ptr is freed. Otherwise
>there may be chances of trying to free the same ptr more than once.

No, it doesn't help at all. You freed the memory and you clobbered
one pointer that referenced it. How many other COPIES of that pointer
are out there? Many times you pass a pointer down many levels of
function calls, and free() can't possibly know where all the copies are.

Gordon L. Burditt
sneaky.lonestar.org!gordon

Dave Schaumann

unread,
Dec 15, 1994, 6:44:51 PM12/15/94
to
In article <D0p1p...@comdev.fdn.fr>, Frederic STARK <f...@comdev.fdn.fr> wrote:
>In article <mjs.786836172@hubcap> m...@hubcap.clemson.edu (M. J. Saltzman)
>writes:
>> My personal favorite way to group statements in a macro is like this:
>>
>> #define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0)
>
>Which is my favorite too

This whole thread seems bizarre to me. I suppose that it *might*
be helpful in some cases to set a pointer to NULL after free()ing
the storage it points to. But if you are going to provide such
a facility, you should name it accordingly:

#define FREE_AND_SET_NULL(ptr) ( free(ptr), (ptr) = NULL )

or better (since it avoids the difficulty the above has when
"ptr" is an expression with a side-effecting operator):

void FREE_AND_SET_NULL( void **ptr ) { free(*ptr) ; *ptr = NULL ; }


>I remember a poster (but not his name, sorry), some weeks ago, that
>suggested to add a 'assign and return old value' operator to C. He called
>it ':='.

IMHO, this is a lousy idea. C *doesn't* need more operators. A much
better fix would be to take the things the preprocessor is legitimately
used for (manifest constants and inline functions) and support them
directly in the language. The preprocessor is probably the best solution
for stuff like include files and conditional compilation, but as this
thread demonstrates, it is a poor fit with the C language itself.

-Dave

--
*** *** *** *** *** *** *** *** *** *** *** *** ***
* * * * * * * * * * * * *
* * * * * * * * * * * * *

Andy Sawyer

unread,
Dec 17, 1994, 6:57:35 AM12/17/94
to
In article <D0p1p...@comdev.fdn.fr> f...@comdev.fdn.fr "Frederic STARK" writes:

> In article <mjs.786836172@hubcap> m...@hubcap.clemson.edu (M. J. Saltzman)
> writes:
> > My personal favorite way to group statements in a macro is like this:
> >
> > #define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0)
>
> Which is my favorite too
>

Why not just:

#define FREE(ptr) { free(ptr); (ptr) = NULL; }


> > or
> >
> > #define FREE(ptr) if (1) { free(ptr); (ptr) = NULL; } else
> >
>
> Personal opinion: I just hate this one:
> FREE(p)
> printf( "Never reached\n" );
> /* Well, sure, the compiler would warn you... */
>

or better:

void foo( )
{
void *bar;

....
FREE(bar);
}
/* Syntax error...*/


Regards,
Andy
--
==========================================================================
| Andy Sawyer Internet (Personal) : an...@thone.demon.co.uk |
| Compu$erve (Business) : 100432,1713 |
==========================================================================

Lars Wirzenius

unread,
Dec 18, 1994, 8:55:45 AM12/18/94
to
da...@CS.Arizona.EDU (Dave Schaumann) writes:
> or better (since it avoids the difficulty the above has when
> "ptr" is an expression with a side-effecting operator):
>
> void FREE_AND_SET_NULL( void **ptr ) { free(*ptr) ; *ptr = NULL ; }

From the FAQ:

2.19: Can I use a void ** pointer to pass a generic pointer to a
function by reference?

A: Not portably. There is no generic pointer-to-pointer type in C.
void * acts as a generic pointer only because conversions are
applied automatically when other pointer types are assigned to
and from void *'s; these conversions cannot be performed (the
correct underlying pointer type is not known) if an attempt is
made to indirect upon a void ** value which points at something
other than a void *.

I do agree that a "free the memory and set the pointer to NULL" approach
is peculiar, if for no other reason than the fact that it is too little
and too much: too little benefit (it doesn't handle other pointers into
the allocated memory block), too much work (have to be careful with
side effects with them macros).

--
Lars.Wi...@helsinki.fi (finger wirz...@klaava.helsinki.fi)
Publib version 0.4: ftp://ftp.cs.helsinki.fi/pub/Software/Local/Publib/

Olly Betts

unread,
Dec 19, 1994, 12:31:16 PM12/19/94
to
In article <787665...@thone.demon.co.uk>,

Andy Sawyer <an...@thone.demon.co.uk> wrote:
>In article <D0p1p...@comdev.fdn.fr> f...@comdev.fdn.fr "Frederic STARK" writes:
>
>> In article <mjs.786836172@hubcap> m...@hubcap.clemson.edu (M. J. Saltzman)
>> writes:
>> > My personal favorite way to group statements in a macro is like this:
>> >
>> > #define FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0)
>>
>> Which is my favorite too
>>
>
> Why not just:
>
> #define FREE(ptr) { free(ptr); (ptr) = NULL; }

Concentrating only on "do { ... } while (0)" vs "{ ... }", because if
you use the latter:

if (ptr)
FREE(ptr);
else
printf("ptr was NULL\n");

becomes:

if (ptr)


{ free(ptr); (ptr) = NULL; };
else

printf("ptr was NULL\n");

and the semicolon after the } in the 'then' clause makes the else a
syntax error.

Olly
--
suckSqueezeBANGblowsuckSqueezeBANGblowsuckSqueezeBANGblowsuckSqueezeBANGblow

Graham Stoney

unread,
Dec 19, 1994, 10:42:18 PM12/19/94
to
ne...@hpqtdya.sqf.hp.com (Neil Gall) writes:
>free() can't change the value of the pointer, as function
>parameters are *always* passed by value in C. So it is guaranteed
>that the pointer will have the same value after the call to free.

This line of reasoning appears reasonable on the surface, but if you read
section 7.10.3 of the standard, you'll find that is is quite legal for the
value of a pointer to be changed simply by passing that value to free(). I
don't know of any systems which actually do things like NULL'ing pointers which
have been passed to free, but it's certainly legal:

7.10.3 Memory management functions
...
The value of a pointer that refers to freed space is indeterminate.

Several people have recently stated that it's impossible for the value of a
pointer to change simply by passing that value to a function; it may be
impossible in most C implementations, but I'm afraid that according to the
standard it's quite legal in cases where the pointer is being free()'d. In
fact, any other pointers referring to the same space are also indeterminate,
so their values could potentially change at the same time.

regards,
Graham

Maurizio Loreti

unread,
Dec 20, 1994, 3:04:27 AM12/20/94
to

I am aware of what the Holy Standard says; but, unless the compiler
implements passing parameters by reference if and only if the called
function is free(), this is simply not possible. I am reading 7.10.3
as "the pointer, if dereferenced, points to a memory region that
contains garbage" - of course, I may be wrong...

Maurizio Loreti http://mvxpd5.pd.infn.it/wwwcdf/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy lor...@padova.infn.it

Alexander V. Lukyanov

unread,
Dec 20, 1994, 8:07:11 AM12/20/94
to
Dave Schaumann (da...@CS.Arizona.EDU) wrote:
: In article <D0p1p...@comdev.fdn.fr>, Frederic STARK <f...@comdev.fdn.fr> wrote:
: >I remember a poster (but not his name, sorry), some weeks ago, that
: >suggested to add a 'assign and return old value' operator to C. He called
: >it ':='.

: IMHO, this is a lousy idea. C *doesn't* need more operators. A much
: better fix would be to take the things the preprocessor is legitimately
: used for (manifest constants and inline functions) and support them
: directly in the language. The preprocessor is probably the best solution
: for stuff like include files and conditional compilation, but as this
: thread demonstrates, it is a poor fit with the C language itself.

I think C need both things. I'd prefer C which has inline functions, consts
and the operator 'assign and return old value'. (I want it all! :-))
Someone suggested to me use C++ for the operator 'assign and return old value',
overload = (In such case I could not use original =).
But why cannot C++ define new operators which don't make
conflicts with existing ones, so that I can define ':=' ?

Alexander Lukyanov
l...@barr.innet.yaroslavl.su

Tanmoy Bhattacharya

unread,
Dec 20, 1994, 11:43:39 AM12/20/94
to
Please followup to appropriate groups only!

In article <1994Dec20...@fnalv.fnal.gov>, lor...@fnalv.fnal.gov (Maurizio Loreti) writes:
|> In article <D13BM...@research.canon.oz.au>, gre...@research.canon.oz.au (Graham Stoney) writes:
|> > ne...@hpqtdya.sqf.hp.com (Neil Gall) writes:
|> >>free() can't change the value of the pointer, as function
|> >>parameters are *always* passed by value in C. So it is guaranteed
|> >>that the pointer will have the same value after the call to free.

<snip>


|> > 7.10.3 Memory management functions
|> > ...
|> > The value of a pointer that refers to freed space is indeterminate.
|> >

<snip>


|> I am reading 7.10.3
|> as "the pointer, if dereferenced, points to a memory region that
|> contains garbage" - of course, I may be wrong...


Not only if dereferenced! You are not allowed to access or compare them either.

Thus in the snippet

void *a=malloc(1);
free(a);
if(a==a) printf("hah!\n");
else printf("nah!\n");

the last lines are undefined. So, by the as if rule, free can change the
pointer to NULL. I do not think a compiler is likely to do it, and
hence I had not posted before.

There is one little caveat: I am crossposting to comp.std.c to ask whether the
following is defined instead of the comparison in the above snippet:

if(*(char*)(void*)&a == *(char*)(void*)&b);

By the way, does my code become defined if I change `malloc(1)' to `NULL' above?

Cheers
Tanmoy
--
tan...@qcd.lanl.gov(128.165.23.46) DECNET: BETA::"tan...@lanl.gov"(1.218=1242)
Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87544-0285,USA H:#3,802,9 St,NM87545
Other networks see <news:news.ansers?internetwork-mail-guide>or
<http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
fax: 1 (505) 665 3003 voice: 1 (505) 665 4733 [ Home: 1 (505) 662 5596 ]

Larry Weiss

unread,
Dec 20, 1994, 12:26:23 PM12/20/94
to
>|> > ne...@hpqtdya.sqf.hp.com (Neil Gall) writes:
><snip>
>|> > 7.10.3 Memory management functions
>|> > ...
>|> > The value of a pointer that refers to freed space is indeterminate.
>|> >
><snip>


I feel that the wording of the Standard's last line in clause 7.10.3 is misleading.
It erroneously implies that the bit pattern representing the value of the pointer
whose value is passed to free() may be changed as a result of the call to free().

"The utility of a pointer that refers to freed space is indeterminate."
would be more accurate.

Actually, the Standard is going beyond it's charter in my opinion to even comment
on possible uses of pointers to freed space. There are lots of nonsensical
possiblities. Why single out just one?

--
Larry Weiss, l...@oc.com
214/888-0471

Tanmoy Bhattacharya

unread,
Dec 21, 1994, 11:50:21 AM12/21/94
to
In article <Maarten.Bos...@rivm.nl>, Maart...@rivm.nl (Maarten Bos) writes:
|> I'm sorry, but I think you miss something here. The pointer does not have to
|> be changed to become indeterminate. After free() it points to 'illegal'
|> memory (because it is freed).

No one said it had to change. But 7.10.3 does seem to allow it to change. (I am
not actually sure of this because any object can be accessed as an array of
characters and hence one does have access to the bit pattern of the object in a
strictly conforming program).

Graham Stoney

unread,
Dec 21, 1994, 10:48:30 PM12/21/94
to
The ISO C Standard says:
> 7.10.3 Memory management functions
> ...
> The value of a pointer that refers to freed space is indeterminate.

lor...@fnalv.fnal.gov (Maurizio Loreti) writes:
>I am aware of what the Holy Standard says; but, unless the compiler
>implements passing parameters by reference if and only if the called
>function is free(), this is simply not possible. I am reading 7.10.3
>as "the pointer, if dereferenced, points to a memory region that
>contains garbage" - of course, I may be wrong...

Well, that's not what it says, so I'm not at all sure why you're reading it
like that. I'm reading it as saying that the value of a pointer that has just
been passed to free() is indeterminate. A compiler would be quite at liberty
to special-case calls to free() and set the pointer passed to NULL after the
call returns. I don't know of any compilers that actually do that, but it's
certainly legal.

regards,
Graham

Maarten Bos

unread,
Dec 21, 1994, 9:12:13 AM12/21/94
to
In article <D13BM...@research.canon.oz.au> gre...@research.canon.oz.au (Graham Stoney) writes:
>From: gre...@research.canon.oz.au (Graham Stoney)
>Subject: Re: Value of ptr after free
>Date: Tue, 20 Dec 1994 03:42:18 GMT

>ne...@hpqtdya.sqf.hp.com (Neil Gall) writes:
>>free() can't change the value of the pointer, as function
>>parameters are *always* passed by value in C. So it is guaranteed
>>that the pointer will have the same value after the call to free.

>This line of reasoning appears reasonable on the surface, but if you read
>section 7.10.3 of the standard, you'll find that is is quite legal for the
>value of a pointer to be changed simply by passing that value to free(). I
>don't know of any systems which actually do things like NULL'ing pointers which
>have been passed to free, but it's certainly legal:

> 7.10.3 Memory management functions
> ...
> The value of a pointer that refers to freed space is indeterminate.

I'm sorry, but I think you miss something here. The pointer does not have to

be changed to become indeterminate. After free() it points to 'illegal'
memory (because it is freed).

>regards,
>Graham


Greetings,

Maarten Bos (Maart...@rivm.nl)

Jim Kingdon

unread,
Jan 12, 1995, 8:30:06 PM1/12/95
to

>Mostly I agree with this, but there is a problem. ANSI Classic section
>3.3.2.2, page 41 lines 33 to 35: "In preparing for the call to a function,
>the arguments are evaluated, and each parameter is assigned the value of
>the corresponding argument." If the function is a standard library function,
>then it does not have to be written in C and might not have parameters. It
>might permissibly have some other means of receiving argument information.
>
>Now, although I believe it was intended to allow library functions not to
>be written in C themselves, I do not believe that this severe a loophole
>was intended. So, let's hope that a TC might fix it and let's continue.

I think library functions need to act as if they were written in C,
for the simple reason that I see no definition of "function" other
than ANSI Classic 3.7.1. Of course this is not strictly speaking what
is intended because C itself has no ability to do things like I/O.
But common sense (yeah, I know, most comp.std.c posters don't believe
in it, but it comes in handy sometimes) clarifies that although the
actual behavior of some functions might not be expressable in C, that
at least things like call-by-value are intended to be required.

>>>I am reading 7.10.3 as "the pointer, if dereferenced, points to a
>>>memory region that contains garbage" - of course, I may be wrong...

>>Not only if dereferenced! You are not allowed to access or compare
>>them either.

>I have read assertions that these effects were intended.

Right. The intended case is (the following example is slightly
hypothetical, but close to what the committee had in mind) a machine
where all pointers are stored in "pointer registers" which consist of
a segment, which indicates which malloc'd block it is in, and an
offset within the segment. Suppose that any access or comparison of
pointers checks the segment against a hardware table of valid
segments, and that free() removes a segment number from the valid
segment table. It is then not necessary for free to do something
besides call-by-value to cause the pointer to become no longer capable
of being accessed or compared.

As for what happens if you access the pointer byte-by-byte, not as a
pointer, I'm not sure there is any guarantee regarding the
correspondance between and object itself and its bytes, so perhaps you
could come up with some twisted interpretation whereby the bytes can
change. But it would appear to be pushing it.

Fergus Henderson

unread,
Jan 17, 1995, 6:28:31 AM1/17/95
to
cs...@csv.warwick.ac.uk (Jules) writes:

>Are two pointers to the same object always guaranteed to be equal by the
>standard?

Yes, so long as you obtained those pointers in a standard-conforming way.

>If so, then most 80x86 compilers have a serious problem

No, those 80x86 compilers don't have the problem you're suggesting.

>as they tend to use
>a straightforward byte by byte comparison such as this, even though the two
>pointers, whose values when cast to longs are 0x10200010 and 0x10210000 (for
>example) point to the same space in memory.

That's not a problem, since if you obtain two pointers to the same
object in a standard-conforming way, the compiler will guaranteed that
they are byte-for-byte equivalent, so it is safe to use a byte-for-byte
comparison. There are no standard-conforming ways to object pointers
which point to the same address but have different segments or different
offsets.

--
Fergus Henderson - f...@munta.cs.mu.oz.au
all [L] (programming_language(L), L \= "Mercury") => better("Mercury", L) ;-)

Andrew Phillips

unread,
Jan 18, 1995, 12:04:51 AM1/18/95
to
Jules (cs...@csv.warwick.ac.uk) wrote:
: Are two pointers to the same object always guaranteed to be equal by the
: standard?

They are guaranteed to compare equal.

: If so, then most 80x86 compilers have a serious problem as they tend to use


: a straightforward byte by byte comparison such as this, even though the two
: pointers, whose values when cast to longs are 0x10200010 and 0x10210000 (for
: example) point to the same space in memory.

IF its possible to have pointers to the same memory location with
different internal representations then the compiler must ensure that
they compare equal. However, I would think that with most compilers
it would be impossible to get two pointers to the same array with
different segment values unless you invoke undefined behaviour in
some way.

BTW The way pointers are converted when cast to longs is
implementation dependent. One compiler I have used would convert
both the pointer values 1020:0010 and 1021:0000 to 0x10210.
Presumably this was to avoid the sorts of problems you mentioned
(although this would still only be useful in programs that invoke
undefined behaviour).

: This has been known to cause
: serious problems in the past, and this is one good reason why normalised
: ("huge") pointers are used, although the use of these is not by default.

I have never heard of this reason for huge. Huge is so that you can
access all elements of an array that won't fit into one segment
(i.e > 64Kbytes).
--
Andrew Phillips (News/Sys Admin) and...@teslab.lab.oz.au +61 2 287 6551
--------------------------------
Just a SPOKE, not a SPOKESPERSON

Stephen Baynes

unread,
Jan 20, 1995, 3:03:06 AM1/20/95
to
Fergus Henderson (f...@munta.cs.mu.OZ.AU) wrote:
: cs...@csv.warwick.ac.uk (Jules) writes:

: >Are two pointers to the same object always guaranteed to be equal by the
: >standard?

: Yes, so long as you obtained those pointers in a standard-conforming way.

: >If so, then most 80x86 compilers have a serious problem

: No, those 80x86 compilers don't have the problem you're suggesting.

: >as they tend to use
: >a straightforward byte by byte comparison such as this, even though the two
: >pointers, whose values when cast to longs are 0x10200010 and 0x10210000 (for
: >example) point to the same space in memory.

: That's not a problem, since if you obtain two pointers to the same
: object in a standard-conforming way, the compiler will guaranteed that
: they are byte-for-byte equivalent, so it is safe to use a byte-for-byte
: comparison. There are no standard-conforming ways to object pointers
: which point to the same address but have different segments or different
: offsets.

It that "all-known-80x86-compilers will guarantee byte-for-byte comparison"
or all "ANSI-conforming-compilers will guarantee byte-for-byte comparison"?
My understanding is that ANSI does not guarantee byte-for-byte comparison
for any types other than byte sized types (by definition signed/unsigned chars).
--
Stephen Baynes bay...@mulsoc2.serigate.philips.nl
Philips Semicondutors Ltd
Southampton My views are my own.
United Kingdom

Tanmoy Bhattacharya

unread,
Jan 21, 1995, 7:54:31 PM1/21/95
to
In article <D2p2D...@ukpsshp1.serigate.philips.nl>, bay...@ukpsshp1.serigate.philips.nl (Stephen Baynes) writes:
|> It that "all-known-80x86-compilers will guarantee byte-for-byte comparison"
|> or all "ANSI-conforming-compilers will guarantee byte-for-byte comparison"?
|> My understanding is that ANSI does not guarantee byte-for-byte comparison
|> for any types other than byte sized types (by definition signed/unsigned chars).

I am not sure it does that for char or signed char either. Wasn't there some
possible problem with `hidden' bits?

But because any object can probably be accessed as unsigned chars, and from the
definition of object as a sequence of bytes, and that unsigned chars are bytes
probably without `holes', byte-equal objects would be equal.

If equality implied byte-equality, the struct hack would probably have been valid
in every reasonable implementation (where would it keep bounds information?).
IEEE arithmetic (with +0. and -0.) or one's complement arithmetic (with +0 and
-0) would have been difficult. (I am assuming one is talking about equality of
objects of the same type.)

In any case, the sub-thread started about equality of pointers of the same type
pointing to the same memory location, not about their byte-equality. The original
thread was about the byte-equality of pointers before and after free. (Equality
cannot be defined, because a pointer after free cannot be compared t all)

By the way does the standard guarantee either of the following (I hope it
guarantees both! At least 2)

Question 1:
struct check {char a; int b;} check = {0,0}, try;
try = check;
assert(memcmp(try,check, sizeof(check)) == 0);

Question 2:
struct check {char a; int b;} check = {0,0}, try;
try = check;
if (memcmp(try,check, sizeof(check)) == 0)
assert(memcmp(try,check,sizeof(check))==0);
else
assert(1);

Cheers
Tanmoy
--
tan...@qcd.lanl.gov(128.165.23.46) DECNET: BETA::"tan...@lanl.gov"(1.218=1242)
Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87544-0285,USA H:#3,802,9 St,NM87545

Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,

Fergus Henderson

unread,
Jan 24, 1995, 6:07:03 AM1/24/95
to
bay...@ukpsshp1.serigate.philips.nl (Stephen Baynes) writes:

>Fergus Henderson (f...@munta.cs.mu.OZ.AU) wrote:
>
>: That's not a problem, since if you obtain two pointers to the same
>: object in a standard-conforming way, the compiler will guaranteed that
>: they are byte-for-byte equivalent, so it is safe to use a byte-for-byte
>: comparison. There are no standard-conforming ways to object pointers
>: which point to the same address but have different segments or different
>: offsets.
>It that "all-known-80x86-compilers will guarantee byte-for-byte comparison"
>or all "ANSI-conforming-compilers will guarantee byte-for-byte comparison"?

I meant the former.

Stephen Baynes

unread,
Jan 23, 1995, 3:35:15 AM1/23/95
to
Norman Diamond (dia...@jrd.dec.com) wrote:
: Answers to two people here.

: In article <3f8pgu$e...@oregano.csv.warwick.ac.uk>, cs...@csv.warwick.ac.uk (Jules) writes:
-snip-
: >As for what happens if you access the pointer byte-by-byte, not as a


: >pointer, I'm not sure there is any guarantee regarding the correspondance
: >between and object itself and its bytes, so perhaps you could come up
: >with some twisted interpretation whereby the bytes can change.

: Some exercises really do require twisting (and I would rarely worry about
: them when writing practical code) but other exercises only use twisting as
: a convenience to make examples smaller or defects more obvious. I believe
: this case is the latter.

Some (non-segmented) systems don't use all the bits of a pointer for the
address. The other bits could be junk, for the aplications own use (some lisp
implementations have made good use of extra bits!), carry type or size
information.

Kevin D. Quitt

unread,
Jan 25, 1995, 10:18:20 AM1/25/95
to
Thus wrote f...@munta.cs.mu.OZ.AU (Fergus Henderson)
>bay...@ukpsshp1.serigate.philips.nl (Stephen Baynes) writes:
>>Fergus Henderson (f...@munta.cs.mu.OZ.AU) wrote:
>>: That's not a problem, since if you obtain two pointers to the same
>>: object in a standard-conforming way, the compiler will guaranteed that
>>: they are byte-for-byte equivalent,
>>It that "all-known-80x86-compilers will guarantee byte-for-byte comparison"
>>or all "ANSI-conforming-compilers will guarantee byte-for-byte comparison"?
>I meant the former.

Of course, its not true, except in HUGE mode on MSC (and possibly
equivalent models on other compilers). The other models provide no such
assurance.

--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91351-4454 96.37% of all statistics are made up

Greg Black

unread,
Jan 30, 1995, 3:29:19 PM1/30/95
to
tan...@qcd.lanl.gov (Tanmoy Bhattacharya) writes:

>By the way does the standard guarantee either of the following (I hope it
>guarantees both! At least 2)

Since both examples are incorrect, I suspect that they are
undefined :-)

>Question 1:
>struct check {char a; int b;} check = {0,0}, try;
>try = check;
>assert(memcmp(try,check, sizeof(check)) == 0);

Should be:

assert(memcmp(&try, &check, sizeof(check)) == 0);

My understanding of this is that a compiler is free to do the
assignment by the equivalent of either of these lines:

try.a = check.a, try.b = check.b;
memcpy(&try, &check, sizeof(check));

And therefore the assertion is allowed to fail. (The gcc
compiler uses the second method; I don't know about other
compilers off the top of my head.)

The fact that you can use the simple assignment operator on
struct operands but not the equality or relational operators
seems to fit the principle that padding does not have to compare
equal. This is supported by the footnote to 7.11.4.1 (memcmp)
which says that the contents of padding holes in structs are
indeterminate.

>Question 2:
>struct check {char a; int b;} check = {0,0}, try;
>try = check;
>if (memcmp(try,check, sizeof(check)) == 0)
> assert(memcmp(try,check,sizeof(check))==0);
>else
> assert(1);

This one is also missing a couple of `&' characters in each of
the memcmp lines. I'm not sure what it buys me ...

--
Greg Black -- g...@gba.oz.au

Clive D.W. Feather

unread,
Feb 10, 1995, 4:21:38 AM2/10/95
to
In article <3fsac7$i...@newshost.lanl.gov>,

Tanmoy Bhattacharya <tan...@qcd.lanl.gov> wrote:
>> My understanding is that ANSI does not guarantee byte-for-byte comparison
>> for any types other than byte sized types (by definition signed/unsigned chars).
> I am not sure it does that for char or signed char either. Wasn't there some
> possible problem with `hidden' bits?

No, but on a ones-complement system (for example) there can be cases where
two different bit patterns with the same value, and which therefore compare
equal. In general, comparison is of *value*; only in the case of unsigned
char is this the same as comparing the bytes.

> struct check {char a; int b;} check = {0,0}, try;
> try = check;
> assert(memcmp(try,check, sizeof(check)) == 0);

This assertion can fail. There is no requirement that any alignment bytes
be copied.

> struct check {char a; int b;} check = {0,0}, try;
> try = check;
> if (memcmp(try,check, sizeof(check)) == 0)
> assert(memcmp(try,check,sizeof(check))==0);

I think we covered this recently, and the consensus was that any alignment
bytes can't just change without reason.

--
Clive D.W. Feather | Santa Cruz Operation | If you lie to the compiler,
cl...@sco.com | Croxley Centre | it will get its revenge.
Phone: +44 1923 813541 | Hatters Lane, Watford | - Henry Spencer
Fax: +44 1923 813818 | WD1 8YN, United Kingdom | <== NOTE: NEW FAX NUMBER

Reply all
Reply to author
Forward
0 new messages