[comp.std.c] Just a minor new twist on free

blodgett@apollo.HP.COM (Bruce Blodgett) (10/12/90)

If you are trying to compile code which may call free() with a NULL
argument, and use an implementation of free() that does not handle NULL
gracefully, try adding one of the following to <stdlib.h>:

#define free(x) ( (x) ? free(x) : ( (void)0 ) )
  or
#define free(x) { void * ptr = (x); if ( ptr != NULL ) free(ptr); }

The former has the side-effect of evaluating the argument to free()
twice.  The latter is a statement rather than an expression of type
void, and therefore wouldn't work if someone tried to embed a call to
free() in an expression (there are not many uses for subexpressions of
type void).
Bruce Blodgett
blodgett@apollo.hp.com
(508) 256-0176 x4037

gdtltr@freezer.it.udel.edu (Gary Duzan) (10/12/90)

In article <4d5780ad.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
=>
=>If you are trying to compile code which may call free() with a NULL
=>argument, and use an implementation of free() that does not handle NULL
=>gracefully, try adding one of the following to <stdlib.h>:
=>
=>#define free(x) ( (x) ? free(x) : ( (void)0 ) )
=>  or
=>#define free(x) { void * ptr = (x); if ( ptr != NULL ) free(ptr); }
=>
=>The former has the side-effect of evaluating the argument to free()
=>twice.  The latter is a statement rather than an expression of type
=>void, and therefore wouldn't work if someone tried to embed a call to
=>free() in an expression (there are not many uses for subexpressions of
=>type void).

   Both will also have the property of recursively expanding free() forever.
Better to call it something else. Your cpp will thank you for it.

                                        Gary Duzan
                                        Time  Lord
                                    Third Regeneration



-- 
                          gdtltr@freezer.it.udel.edu
   _o_                    --------------------------                      _o_
 [|o o|]        An isolated computer is a terribly lonely thing.        [|o o|]
  |_O_|         "Don't listen to me; I never do." -- Doctor Who          |_O_|

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (10/12/90)

In article <4d5780ad.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
> If you are trying to compile code which may call free() with a NULL
> argument, and use an implementation of free() that does not handle NULL
> gracefully, try adding one of the following to <stdlib.h>:
> #define free(x) ( (x) ? free(x) : ( (void)0 ) )
> #define free(x) { void * ptr = (x); if ( ptr != NULL ) free(ptr); }

Much better:

  #define free(x) ( ( __frx = x ) , ( __frx ? __frol(__frx) : (void) 0 ) )
  extern void *__frx;
  extern void (*__frol)();

In the library source, undef free, define __frx, and define __frol
initialized to &free.

---Dan

rbutterworth@watmath.waterloo.edu (Ray Butterworth) (10/12/90)

In article <10066:Oct1212:30:5790@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Much better:
>  #define free(x) ( ( __frx = x ) , ( __frx ? __frol(__frx) : (void) 0 ) )
>  extern void *__frx;
>  extern void (*__frol)();

Which will blow up if an interrupt occurs and changes the value of __frx
between the assignment and the test, or the test and the __frol call.
(Considering the environment under which C was developed,
 it's amazing how non-reentrant so much of the library is.)

In article <4d5780ad.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
> #define free(x) { void * ptr = (x); if ( ptr != NULL ) free(ptr); }

You should call it FREE, but even then something like
"if (test) FREE(thing); else something_else();"
would give a syntax error.

Macros like that should be written as
#define NAME(arg) do { auto thing=arg; ... ; } while(0)
They still can't be used as expressions,
but at least they can be used in "if" statements.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (10/14/90)

In article <1990Oct12.162928.21807@watmath.waterloo.edu> rbutterworth@watmath.waterloo.edu (Ray Butterworth) writes:
> In article <10066:Oct1212:30:5790@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >Much better:
> >  #define free(x) ( ( __frx = x ) , ( __frx ? __frol(__frx) : (void) 0 ) )
> >  extern void *__frx;
> >  extern void (*__frol)();
> Which will blow up if an interrupt occurs and changes the value of __frx
> between the assignment and the test, or the test and the __frol call.

So what? The system's free() isn't reentrant either. Now do you see
something incorrect about my implementation, or are you just posting so
you can complain about how difficult it is to use threads in C? If the
latter, try proposing some solutions in alt.lang.cfutures.

---Dan

pds@lemming.webo.dg.com (Paul D. Smith) (10/15/90)

[] ... try adding one of the following to <stdlib.h>

Oh no! Not that!  *Never* *ever* *change* the standard libraries which
ship with your compiler! (unless they don't work ;-)  Put it in some
local header file please, I don't want to change my nice, working,
ASNI-compliant header files in order to compile your program...

-- This has been a public service announcement from your local
-- ANSI-promoter; any flames by e-mail please!
--

                                                                paul
-----
 ------------------------------------------------------------------
| Paul D. Smith                          | pds@lemming.webo.dg.com |
| Data General Corp.                     |                         |
| Network Services Development           |   "Pretty Damn S..."    |
| Open Network Applications Department   |                         |
 ------------------------------------------------------------------

jtc@van-bc.wimsey.bc.ca (J.T. Conklin) (10/16/90)

In article <PDS.90Oct15104036@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
>Oh no! Not that!  *Never* *ever* *change* the standard libraries which
>ship with your compiler! (unless they don't work ;-)  Put it in some
>local header file please, I don't want to change my nice, working,
>ANSI-compliant header files in order to compile your program...

At UniFax, we ANSIfy the development environment on all of our
development machines.  Header files get protoized and missing
functions get added to the C library.

It is hoped that the vendors will finally get the idea, but until then
we feel that maintaining these development environments is worth the
effort.

	--jtc

-- 
J.T. Conklin	UniFax Communications Inc.
		...!{uunet,ubc-cs}!van-bc!jtc, jtc@wimsey.bc.ca

pds@lemming.webo.dg.com (Paul D. Smith) (10/17/90)

[] In article <PDS.90Oct15104036@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
[] >Oh no! Not that!  *Never* *ever* *change* the standard libraries which
[] >ship with your compiler! (unless they don't work ;-)  Put it in some
[] >local header file please, I don't want to change my nice, working,
[] >ANSI-compliant header files in order to compile your program...

[] At UniFax, we ANSIfy the development environment on all of our
[] development machines.  Header files get protoized and missing
[] functions get added to the C library.

I'd say all this falls under the "unless they don't work" category! :-)  
Even so, as has already been mentioned, there are probably better ways
of doing it than changing the standard includes.

I have more than once been bitten by adding/changing things in the /
and /usr directories which were shipped with the product, and having
many things not work (I once changed the owner of /usr/bin/login to
"bin" instead of root; now just *try* to login as anything except
root!  And it took a whole day to discover the problem.)

What do you do if you need to compile a program which relies on the
old headers?
--

                                                                paul
-----
 ------------------------------------------------------------------
| Paul D. Smith                          | pds@lemming.webo.dg.com |
| Data General Corp.                     |                         |
| Network Services Development           |   "Pretty Damn S..."    |
| Open Network Applications Department   |                         |
 ------------------------------------------------------------------

jtc@van-bc.wimsey.bc.ca (J.T. Conklin) (10/18/90)

[Followup to comp.lang.c]

In article <PDS.90Oct17102409@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
>[] At UniFax, we ANSIfy the development environment on all of our
>[] development machines.  Header files get protoized and missing
>[] functions get added to the C library.
>
>I'd say all this falls under the "unless they don't work" category! :-)  
>Even so, as has already been mentioned, there are probably better ways
>of doing it than changing the standard includes.

If it can me done well, it is a definite bonus.  The source code of
your project or product can remain relatively free of #ifdef's.  I
have found that this has significantly improved maintainability.

>I have more than once been bitten by adding/changing things in the /
>and /usr directories which were shipped with the product, and having
>many things not work (I once changed the owner of /usr/bin/login to
>"bin" instead of root; now just *try* to login as anything except
>root!  And it took a whole day to discover the problem.)

>What do you do if you need to compile a program which relies on the
>old headers?

It is possible to carefully edit the standard header files to work
with both old and new behaviors; but it is inevitable that once you
have everything working, someone will do an OS upgrade and blow away
your hard work. 

Since we use gcc on most platforms, we don't convert the headers ---
we just copy everything in /usr/include into /usr/local/lib/gcc-include
and make modifications there. In this manner, the stock development
system is independent of our custom "ANSIzed" version.  Other systems
may have flags that point the compiler to look in another directory
for your header directories.

	--jtc

-- 
J.T. Conklin	UniFax Communications Inc.
		...!{uunet,ubc-cs}!van-bc!jtc, jtc@wimsey.bc.ca

darcy@druid.uucp (D'Arcy J.M. Cain) (10/19/90)

In article <PDS.90Oct17102409@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
Seems an attribution was left off but looks like ?@van-bc.wimsey.bc.ca said:
>[] In article <PDS.90Oct15104036@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
>[] >Oh no! Not that!  *Never* *ever* *change* the standard libraries which
>
>[] At UniFax, we ANSIfy the development environment on all of our
>
>I'd say all this falls under the "unless they don't work" category! :-)  
>Even so, as has already been mentioned, there are probably better ways
>of doing it than changing the standard includes.
>
When I installed gcc on my system I modified it to look in /usr/newinclude
for headers and then in /usr/include if not found.  I then copied header
files into the new directory and modified them.  This leaves the original
header files untouched and in fact cc will still work if necessary using
the old header files.  What's the point of having an ANSI compiler if you
don't have the ANSI standard prototypes?

-- 
D'Arcy J.M. Cain (darcy@druid)     |
D'Arcy Cain Consulting             |   I support gun control.
West Hill, Ontario, Canada         |   Let's start with the government!
+ 416 281 6094                     |