[comp.std.c] realloc

scs@adam.pika.mit.edu (Steve Summit) (03/29/89)

Today, for the third time in half as many years, I got badly
burned, and wasted lots of time, due to a bug in a certain
vendor's implementation of realloc.  It is an apparently well-
kept secret that realloc is supposed to behave gracefully at
a slightly special-cased boundary point: when handed a NULL
pointer and a nonzero size, it acts essentially as a malloc.

If you have ever implemented a C run-time library, or if you are
implementing one now, or if you may ever implement one, or if you
know anyone who falls into any of these categories, pay attention:
begin your realloc() implementation with the equivalent of:

	char *realloc(ptr, size)
	char *ptr;
	int size;
	{
	if(ptr == NULL)
		return malloc(size);
	...

The ptr argument and realloc's return value may be void *'s, and
the size argument may be an unsigned or a size_t; the essential
point I am making is the test for NULL and the call of malloc.

This is a short message, so that people who don't read long
articles will see it.  I'll hold further explanations and
justifications for another day.

                                            Steve Summit
                                            scs@adam.pika.mit.edu

davidl@intelob.intel.com (David Levine) (03/29/89)

In article <10170@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>                                  ... It is an apparently well-
>  kept secret that realloc is supposed to behave gracefully at
>  a slightly special-cased boundary point: when handed a NULL
>  pointer and a nonzero size, it acts essentially as a malloc.

The System V Interface Definition (which, despite its many flaws, IS
an established standard, unlike the pANS which is still only a "draft
proposed standard") doesn't require this behavior.  The documentation
for UNIX System V, BSD 4.3, and ULTRIX doesn't mention any special
behavior for reallocing a null pointer; in fact, they all say that
attempting to realloc a pointer that was not returned by malloc,
calloc, or realloc will have unexpected results.  (Yes, malloc can
return a null pointer... I think that they meant a pointer returned by
a SUCCESSFUL call to malloc, calloc, or realloc.)

This means that you are depending on an undocumented feature.  You
shouldn't be surprised when it breaks.

The behavior you describe IS required by the pANS.  You can depend on
this behavior in any ANSI-Standard implementation, but if you expect
it of any System V, BSD, or ULTRIX implementation (and quite possibly
many others), you're expecting something that isn't promised by the
manufacturer.  This, of course, is the whole point of standards.
Unfortunately, there are as yet no ANSI-Standard implementations,
since there is no approved Standard yet.

            David D. Levine                BBBBBBBBB  IIII IIII NNN  NNNN TM
        Senior Technical Writer            BBBB  BBBB iiii iiii NNNN NNNN
                                           BBBBBBBBB  IIII IIII NNNNNNNNN
UUCP: ...[!uunet]!tektronix!biin!davidl    BBBB  BBBB IIII IIII NNNN NNNN
MX-Internet: <davidl@intelob.intel.com>    BBBBBBBBB  IIII IIII NNNN  NNN
ARPA: <@iwarp.intel.com:davidl@intelob.intel.com>

gregg@ihlpb.ATT.COM (Wonderly) (03/29/89)

From article <10170@bloom-beacon.MIT.EDU>, by scs@adam.pika.mit.edu (Steve Summit):
> Today, for the third time in half as many years, I got badly
> burned, and wasted lots of time, due to a bug in a certain
> vendor's implementation of realloc.  It is an apparently well-
> kept secret that realloc is supposed to behave gracefully at
> a slightly special-cased boundary point: when handed a NULL
> pointer and a nonzero size, it acts essentially as a malloc.

I read the man page for realloc and it said nothing about this.  Is it
not possible for you to type

	if (ptr == NULL)
		ptr = malloc (nbytes);
	else
		ptr = realloc (ptr, nbytes);

or are you one of those people that assumes (*((char *)NULL) == 0) too?
This damn lazy programming and sorry excuses for not being defensive has
got to stop.  Hiding all of the magic in the inards of the implementation
does not make it any easier for people to understand the code!  I have
never assumed that realloc() would accept a NULL pointer and if I ever
saw the type of coding that you talk about I would instantly say BUG.
Its like seeing "malloc (strlen (s));".  I know it is W-R-O-N-G!

-- 
Gregg Wonderly                             DOMAIN: gregg@ihlpb.att.com
AT&T Bell Laboratories                     UUCP:   att!ihlpb!gregg

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/29/89)

In article <10170@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>Today, for the third time in half as many years, I got badly
>burned, and wasted lots of time, due to a bug in a certain
>vendor's implementation of realloc.  It is an apparently well-
>kept secret that realloc is supposed to behave gracefully at
>a slightly special-cased boundary point: when handed a NULL
>pointer and a nonzero size, it acts essentially as a malloc.

While that's required for ANSI C standard conformance, in fact
many existing C implementations do not behave that way, and it
isn't advertised behavior even in the current UNIX release (I
don't think it even works that way).  Therefore it is unwise to
rely on this behavior in an application intended for a
not-necessarily-ANSI-conforming environment.

So why standardize this uncommon behavior?  I think the intent
was to make programming easier at some future date when nearly
all C environments will be standard conforming.

consult@osiris.UUCP (Unix Consultation Mailbox ) (03/30/89)

In article <10170@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>It is an apparently well-
>kept secret that realloc is supposed to behave gracefully at
>a slightly special-cased boundary point: when handed a NULL
>pointer and a nonzero size, it acts essentially as a malloc.

I'll say it's well-kept, neither the 4.2BSD nor SysV.2 manpages imply
that calling realloc with first argument of 0 will do anything useful,
let alone that it's *supposed* to.  The SunOS 4.0.0 manpage even says
that "[realloc will fail if] an invalid argument was specified.  The
value of ptr passed to [realloc] must be a pointer to a block previously
allocated by malloc, calloc, realloc, valloc, or memalign."  I'm afraid
0 doesn't qualify as a pointer to a legitimately-allocated block, so
realloc *should* fail in this situation with errno == EINVAL.  That's a
far cry from "is supposed to ... [act] as a malloc."

I suggest that you be more careful in the future about which effects
of library functions are required and which are arbitrary and unreliable.
(I wish all our programmers would do that too, it would keep me from
having to do stupid things with null ptrs in my case-insensitive strcmp
and other such garbage.)


Phil Kos

jym@wheaties.ai.mit.edu (Jym Dyer) (03/30/89)

In article <10032@ihlpb.ATT.COM> gregg@ihlpb.ATT.COM (Wonderly) writes:
> From article <10170@bloom-beacon.MIT.EDU>, by scs@adam.pika.mit.edu (Steve Summit):
>> It is an apparently well-kept secret that realloc is supposed to behave
>> gracefully at a slightly special-cased boundary point: when handed a NULL
>> pointer and a nonzero size, it acts essentially as a malloc.

Actually, that's a new innovation.  A good one, though.

> Is it not possible for you to type
>
>	if (ptr == NULL)
>		ptr = malloc (nbytes);
>	else
>		ptr = realloc (ptr, nbytes);

Possible, but not desirable.  If you're going to have to use this if/else
 statement every time you use realloc(), you might as well put it into
  realloc().  And that's why ANSI-conforming realloc()s do just that.

> . . . or are you one of those people that assumes (*((char *)NULL) == 0) too?
> This damn lazy programming and sorry excuses for not being defensive has
> got to stop.

I saw no such assumption, no "damn lazy programming" and no "sorry excuses
 for not being defensive."  Steve Summit's article was, in fact, quite
  helpful.
   <_Jym_>

Tim_CDC_Roberts@cup.portal.com (03/30/89)

In <10170@bloom-beacon.MIT.EDU>, scs@adam.pika.mit.edu (Steve Summit) writes:

> It is an apparently well-
> kept secret that realloc is supposed to behave gracefully at
> a slightly special-cased boundary point: when handed a NULL
> pointer and a nonzero size, it acts essentially as a malloc.

I am unable to locate any justification for this statement.  Is this
behavior actually defined anywhere, or is it just your wish that realloc
behave this way?

Tim_CDC_Roberts@cup.portal.com                | Control Data...
...!sun!portal!cup.portal.com!tim_cdc_roberts |   ...or it will control you.

ark@alice.UUCP (Andrew Koenig) (03/30/89)

In article <10032@ihlpb.ATT.COM>, gregg@ihlpb.ATT.COM (Wonderly) writes:

> I read the man page for realloc and it said nothing about this.  Is it
> not possible for you to type
> 
> 	if (ptr == NULL)
> 		ptr = malloc (nbytes);
> 	else
> 		ptr = realloc (ptr, nbytes);
> 
> or are you one of those people that assumes (*((char *)NULL) == 0) too?
> This damn lazy programming and sorry excuses for not being defensive has
> got to stop.

Hm.  Here's what my draft ANSI C spec has to say about realloc:

	void *realloc(void *ptr, size_t size);

The realloc function changes the size of the object pointed to by
`ptr' to the size specified by `size.'  The contents of the object
shall be unchanged up to the lesser of the new and old sizes.  If
the new size is larger, the value of the newly allocated portion
of the object is indeterminate.  If `ptr' is a null pointer, the
realloc function behaves like the malloc function for the
specified size...

---------

Of course, not all C implementations behave this way.  This
leaves C programmers in a bind: rely on this behavior or not?  If
not, how does one determine which behavior can be trusted?  If
so, what does one do when one's code breaks on various machines?
-- 
				--Andrew Koenig
				  ark@europa.att.com

henry@utzoo.uucp (Henry Spencer) (03/30/89)

In article <10170@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>... It is an apparently well-
>kept secret that realloc is supposed to behave gracefully at
>a slightly special-cased boundary point: when handed a NULL
>pointer and a nonzero size, it acts essentially as a malloc.

Unfortunately, this is (at present) not a portable assumption, because
neither V6 nor V7 Unix -- the Unixes from which essentially all others
are descended, and which included the first widely-known C compilers -- 
did this.  It was invented later.  There are probably a fair number
of old systems that haven't caught up with it.  (It *is* in ANSI C as
of the Oct. draft, so it will *eventually* be a portable assumption.)
-- 
Welcome to Mars!  Your         |     Henry Spencer at U of Toronto Zoology
passport and visa, comrade?    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

scjones@sdrc.UUCP (Larry Jones) (03/30/89)

In article <10170@bloom-beacon.MIT.EDU>, scs@adam.pika.mit.edu (Steve Summit) writes:
> Today, for the third time in half as many years, I got badly
> burned, and wasted lots of time, due to a bug in a certain
> vendor's implementation of realloc.  It is an apparently well-
> kept secret that realloc is supposed to behave gracefully at
> a slightly special-cased boundary point: when handed a NULL
> pointer and a nonzero size, it acts essentially as a malloc.

And when handed a non-NULL pointer and a zero size, it acts like
free.  This behavior is required by the draft ANSI Standard.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"When all else fails, read the directions."

johns@calvin.EE.CORNELL.EDU (John Sahr) (03/30/89)

In article <10032@ihlpb.ATT.COM> gregg@ihlpb.ATT.COM (Wonderly) writes:
>From article <10170@bloom-beacon.MIT.EDU>, by scs@adam.pika.mit.edu (Steve Summit):
[ Mr. Summit complains that ptr = realloc(ptr,nbytes) does not behave like 
ptr = malloc(nbytes) when ptr is NULL. ]

>I read the man page for realloc and it said nothing about this...

There are two different reallocs on my system, the usual realloc(3c) and
another realloc(3x).  Neither one specifies the behaviour of realloc()
when ptr is NULL.  The man for realloc(3x) says "undocumented features
of malloc(3c) have not been duplicated." Not realloc(3c), but malloc(3c).

My realloc(3c) man does say that it will handle a pointer to a block that
was previously free(3c)'d.  

I have been working on a program recently where realloc became quite 
handy.  After a while, I realized that every place I used realloc, I was
also using malloc, a la

>Is it not possible for you to type
>
>	if (ptr == NULL)
>		ptr = malloc (nbytes);
>	else
>		ptr = realloc (ptr, nbytes);
>
>or are you one of those people that assumes (*((char *)NULL) == 0) too?

So, I tried using ptr = realloc(ptr,nbytes) without the ptr == NULL check.
It worked, at least for (3c).  But Mr. Wonderly is correct to the extent
this behaviour is not documented in the man pages, and therefore _should
not be relied upon_.

>This damn lazy programming and sorry excuses for not being defensive has
>got to stop.  Hiding all of the magic in the inards of the implementation
>does not make it any easier for people to understand the code! 

True enough, in general.  In this case, however, it seems "clear" to me 
what is going on.  If you never rely on the ptr == NULL behaviour, you 
can still write if(ptr == NULL).....else....., and it will do the same 
thing, and be "clear."  Clarity, however, is in the eye of the beholder, as 
the discussion on indentation and bracket location indicated a few months
back.

As far as the magic in the innards, it strikes me that realloc(3c)'s
function of copying the old contents into the possibly moved and different
sized block is more "magical" than behaving like malloc(3c) if ptr == NULL.
One could always call memcpy() if one wanted to be more "clear" when this
behaviour is needed.

[deletions]
>Gregg Wonderly                             DOMAIN: gregg@ihlpb.att.com
>AT&T Bell Laboratories                     UUCP:   att!ihlpb!gregg



-- 
John Sahr,                          School of Elect. Eng.,  Upson Hall   
                                    Cornell University, Ithaca, NY 14853

ARPA: johns@calvin.ee.cornell.edu; UUCP: {rochester,cmcl2}!cornell!calvin!johns

gmt@arizona.edu (Gregg Townsend) (03/31/89)

realloc() is sometimes used to grow a list of objects as entries are added. 
If it's to be used with an initially empty list, realloc() must accept a null
pointer as its frist argument -- because ANSI C allows malloc() to return NULL
in response to a request of size zero!

    Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
    +1 602 621 4325      gmt@Arizona.EDU       110 57 16 W / 32 13 45 N / +758m

bader+@andrew.cmu.edu (Miles Bader) (03/31/89)

scjones@sdrc.UUCP (Larry Jones) writes:
> And when handed a non-NULL pointer and a zero size, it acts like
> free.  This behavior is required by the draft ANSI Standard.

Does it return NULL in this case (when it acts like free)?  If so, how
extra-ordinarily convenient...

-Miles

tainter@ihlpb.ATT.COM (Tainter) (03/31/89)

In article <9118@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
>Hm.  Here's what my draft ANSI C spec has to say about realloc:

>	void *realloc(void *ptr, size_t size);
>  If `ptr' is a null pointer, the
>realloc function behaves like the malloc function for the
>specified size...

>Of course, not all C implementations behave this way.

This just serves to remind us all that there is ONE and ONLY ONE good
use for the __ANSI define, put the following at the top of your files:

#ifndef __ANSI

This text should not compile and will produce errors.  This should show you
uou don't want to compile this anywhere but where __ANSI is defined.

#endif

--johnathan.a.tainter--

guy@auspex.UUCP (Guy Harris) (03/31/89)

>I'll say it's well-kept, neither the 4.2BSD nor SysV.2 manpages imply
>that calling realloc with first argument of 0 will do anything useful,
>let alone that it's *supposed* to.  The SunOS 4.0.0 manpage even says
>that "[realloc will fail if] an invalid argument was specified.

Yes.  However, the December 7, 1988 dpANS says:

	4.10.3.4 The "realloc" function

	Synopsis

		#include <stdlib.h>
		void *realloc(void *ptr, size_t size);

	Description

	  ... If "ptr" is a null pointer, the "realloc" function behaves
	like the "malloc" function for the specified size.

So, while the "well-kept secret" was, indeed, a secret in earlier
systems - since *no* promise about the behavior was listed in the
documentation - it's not likely to be a secret in ANSI C, unless that bit
gets deleted before the standard is issued.

So basically:

	1) if you know you'll only be running in ANSI C environments,
	   feel free to pass NULL as the first argument to "realloc"
	   (assuming that, in that case, you expect it to do a "malloc");

	2) if you *don't* know that, make sure all the assumptions you
	   made about your environment are backed up by the
	   documentation before you port to a new environment.

djones@megatest.UUCP (Dave Jones) (03/31/89)

I guess this is all figured out now.

My $.02:

1. The first posting may have had just a hint of flame to it, but
   there was no call to heap such a raft of shit on the guy.
   I've been reading the net for over four years, and I am still sometimes
   amazed by the vitriol that purely technical discussions can elicit.
   (Grumble, mumble, snort.)

2. Just because the ANSII draft says that realloc((char*)0, size) is supposed
   to be cool does not mean it ever will be universally portable.  (I
   wonder why they did it.  Looks like asking for trouble.)   ANSII can
   only legislate what ANSII-conforming compilers do.  I expect variants
   of the old runtime libraries to be around as long as I live, (and I'm 
   trying to eat more vegetables and get some walking in, so that could
   be *years*!).

djones@megatest.UUCP (Dave Jones) (03/31/89)

From article <681@sdrc.UUCP>, by scjones@sdrc.UUCP (Larry Jones):
> 
> And when handed a non-NULL pointer and a zero size, it acts like
> free.  This behavior is required by the draft ANSI Standard.
> 


Gack.

The realloc((char*)0, size) thing was bad enough. What's this all
about?

Stuff like this just makes it hard to port ANSII programs to
old systems. Also makes it harder to convert an old system to ANSII.
I can't think of any good reason to add such a silly spec. What am I
missing?

Can anyone suggest a legitimate reason why they would want to do such
a thing?

daveb@geaclib.UUCP (David Collier-Brown) (03/31/89)

 In article <10032@ihlpb.ATT.COM>, gregg@ihlpb.ATT.COM (Wonderly) writes:
| I read the man page for realloc and it said nothing about this.  Is it
| not possible for you to type ...

From article <9118@alice.UUCP>, by ark@alice.UUCP (Andrew Koenig):
| Hm.  Here's what my draft ANSI C spec has to say about realloc:
| ...  the object is indeterminate.  If `ptr' is a null pointer, the
| realloc function behaves like the malloc function for the
| specified size...
| 

Ok, its a verbal dispute (ie, one which can  be resolved by looking
something up).  now, on to the C question:
 
| Of course, not all C implementations behave this way.  This
| leaves C programmers in a bind: rely on this behavior or not?  If
| not, how does one determine which behavior can be trusted?  If
| so, what does one do when one's code breaks on various machines?

  Firstly, one provides a compile-time test for the behavior of
realloc, and then one compiles a wrapper if necessary.    To do this,
write a function that tries to break realloc, compile it and run it
to produce a value testable by a makefile.  If the makefile finds a
"core" file, an error status or an "i failed, but survived" status,
add the following:
void *	theNameOfMyRealloc(void *ptr, size_t size) {
	return (ptr == NULL || *ptr == NULL)? malloc(size):
		realloc(ptr,size);
}
otherwise add
#define theNameOfMyRealloc(ptr,size) realloc(ptr,size)
to the compilation of the libraries.

Morven's Metatheorum:
	Any problem in computer science can be solved by using
exactly the right number of levels of indirection.  Usually adding
one more does the job.

--dave (the Morven in question is Dr. Morven Gentleman, formerly
	of the University, Waterloo) c-b
-- 
 David Collier-Brown.  | yunexus!lethe!dave
 Interleaf Canada Inc. |
 1550 Enterprise Rd.   | He's so smart he's dumb.
 Mississauga, Ontario  |       --Joyce C-B

mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) (03/31/89)

In article <DAVIDL.89Mar29091834@intelob.intel.com> davidl@intelob.intel.com (David Levine) writes:
>The System V Interface Definition (which, despite its many flaws, IS
>an established standard, unlike the pANS which is still only a "draft
>proposed standard") doesn't require this behavior. 

One of the SVID's biggest flaws is that it is NOT a standard: it was never 
balloted and approved by anyone.  It is an interface specification for a 
particular implementation of Unix.  It should be noted that there few 
companies, if any, which have SVID conforming interfaces; even AT&T doen't 
conform to their own interface specification.

The SVID is one of the base documents for some of the P1003 working groups 
because it represents one of the most comprehensive descriptions of Unix 
currently available.  The SVID along with work done by /usr/group provided 
a lot of groundwork for p1003, which IS a standard, and provided some 
impetus for X3J11 which is currently jumping through the final hoops to 
become a standard.

If the SVID were a standard, there would have been no need for P1003.
Unfortunately, there were a couple of hole in the SVID which you could
drive trucks through, hence P1003.


-- 
Mark H. Colburn                  "Look into a child's eye;
Minnetech Consulting, Inc.        there's no hate and there's no lie;
mark@jhereg.mn.org                there's no black and there's no white."

andrew@alice.UUCP (Andrew Hume) (03/31/89)

gregg townsend reminds us of the pANS ``feature'' that malloc(0) returns NULL.
can anyone provide the (or any) justification of this pointless stupid
definition? i just love the idea that an initialised pointer is SOMETIMES
indistinguishable from an uninitialised pointer.

ka@june.cs.washington.edu (Kenneth Almquist) (03/31/89)

ark@alice.UUCP (Andrew Koenig) writes (r. e. the ANSI realloc function):
> Of course, not all C implementations behave this way.  This
> leaves C programmers in a bind: rely on this behavior or not?  If
> not, how does one determine which behavior can be trusted?  If
> so, what does one do when one's code breaks on various machines?

Given that the ANSI standard hasn't even been officially released,
C programmers shouldn't rely on this behavior now.  Maybe five years
from now we will find that virtually everyone has ANSI conformant C
libraries and we can start taking advantage of the ANSI realloc routine.
Until then, it's less of a hassle to type in a few extra lines of code
rather than having your code break in mysterious ways when it is ported
to a non-ANSI system.  The ANSI realloc is different from the majority
of ANSI features, which will cause your program to fail to compile on a
non-ANSI system and can therefore be adopted more aggressively.

As for Andrew's question about what programmer's *can* rely on, the
answer is the current de facto standard, which consists of the
language as defined in the first edition of K&R plus some later
enhancements to the language.  Exactly what is included in this
de facto standard is a matter of opinion, which is one reason for
the ANSI standard.
				Kenneth Almquist

guy@auspex.auspex.com (Guy Harris) (03/31/89)

 >Unfortunately, this is (at present) not a portable assumption, because
 >neither V6 nor V7 Unix -- the Unixes from which essentially all others
 >are descended, and which included the first widely-known C compilers -- 
 >did this.  It was invented later.  There are probably a fair number
 >of old systems that haven't caught up with it.

In fact, I checked the S5R3 "malloc"s - both the one in "libc", which
is, as I remember, little changed from the V7 one, and the one in
"-lmalloc" - and they most definitely do not make the check for NULL, so
there are probably a fair number of *new* systems that haven't caught up
with it.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/01/89)

In article <3229@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>Can anyone suggest a legitimate reason why they would want to do such
>a thing?

I already did that.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/01/89)

In article <740@jhereg.Jhereg.MN.ORG> mark@jhereg.MN.ORG (Mark H. Colburn) writes:
>One of the SVID's biggest flaws is that it is NOT a standard: it was never 
>balloted and approved by anyone.

That's not a necessary criterion for a standard.

>It is an interface specification for a particular implementation of Unix.

That argument was rejected by Federal courts during the AFCAC-251 appeals.
The SVID is a useful specification for waht constitutes "UNIX
functionality", much more so than any available alternative.
It certainly is not logically tied to a particular implementation,
although for economic reasons most would license AT&T's product rather
than start from scratch.

>If the SVID were a standard, there would have been no need for P1003.
>Unfortunately, there were a couple of hole in the SVID which you could
>drive trucks through, hence P1003.

Nah, IEEE P1003's formation had little to do with the SVID.

bright@Data-IO.COM (Walter Bright) (04/01/89)

In article <9118@alice.UUCP< ark@alice.UUCP (Andrew Koenig) writes:
<In article <10032@ihlpb.ATT.COM<, gregg@ihlpb.ATT.COM (Wonderly) writes:
<< I read the man page for realloc and it said nothing about this.  Is it
<< not possible for you to type
<< 	if (ptr == NULL)
<< 		ptr = malloc (nbytes);
<< 	else
<< 		ptr = realloc (ptr, nbytes);
<Hm.  Here's what my draft ANSI C spec has to say about realloc:
<	[stuff deleted]
<Of course, not all C implementations behave this way.  This
<leaves C programmers in a bind: rely on this behavior or not?  If
<not, how does one determine which behavior can be trusted?  If
<so, what does one do when one's code breaks on various machines?

I am involved daily with porting code between PCs, Suns, Apples, Vaxes,
etc. The quality of C compilers varies widely, as does the conformance
to ANSI C. What I have done is create a file called 'missing.c' in
which I write functional equivalents of ANSI C library functions. They
are #ifdef'd in for those primitive compilers that don't have them.
For instance, BSD Unix doesn't have memcpy, so I have:

#if BSDUNIX || VAX11C
char *memcpy(t,f,n)
#if BSDUNIX
char *t,*f;
int n;
{
	bcopy(f,t,n);
	return t;
}
#else
register char *t,*f;
register int n;
{
	char *retval = t;

	while (n--) *t++ = *f++;
	return retval;
}
#endif
#endif

(VAX11C is my euphamism for DEC's C compiler.)

I have dealt with the primitive realloc's by always using a function
mem_realloc, and defining it as:

#if __STDC__
#define mem_realloc realloc
#else
void *mem_realloc(oldmem_ptr,newnumbytes)
void *oldmem_ptr;
unsigned newnumbytes;
{   extern void *realloc(),*malloc();
    void *p;

    if (oldptr == NULL)
	p = newnumbytes ? malloc(newnumbytes) : NULL;
    else if (newnumbytes == 0)
    {	free(oldptr);
	p = NULL;
    }
    else
	p = realloc(oldptr,newnumbytes);
    /*printf("realloc(x%lx,%d) = x%lx\n",oldptr,newnumbytes,p);*/
    return p;
}
#endif

If I'm using a compiler which has a broken realloc(), (which is common!)
I can reimplement my mem_realloc as using a malloc/memcpy/free combination.

Using this approach I can use ANSI library function semantics and still
work with archaic compilers. The application code doesn't have to be
littered with crutches for this stuff, it's isolated away.

hascall@atanasoff.cs.iastate.edu (John Hascall) (04/01/89)

In article <9122@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes:


>gregg townsend reminds us of the pANS ``feature'' that malloc(0) returns NULL.
>can anyone provide the (or any) justification of this pointless stupid
>definition? i just love the idea that an initialised pointer is SOMETIMES
>indistinguishable from an uninitialised pointer.

     And what would you have it return?   An Address?  ...which points to
     zero bytes of allocated storage?  And would successive malloc(0)
     calls return the same pointer? (you're not using any heap with each
     call)  And then consider doing a "free" on such a pointer.

     Just think of malloc(NULL) as not initialising the pointer,
     just as malloc(MORE_BYTES_THAN_WE_GOT) doesn't.

John Hascall

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/01/89)

In article <9122@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes:
>gregg townsend reminds us of the pANS ``feature'' that malloc(0) returns NULL.
>can anyone provide the (or any) justification of this pointless stupid
>definition?

Sure.  malloc() either fails or it succeeds.  If it were required to
succeed for a 0-sized allocation attempt, then additional semantics
would have had to have been devised to deal with the 0-sized object
pointed to by the returned non-null pointer.  For example, should
a series of malloc(0) calls return distinct pointers?  Anyway, for
the limited additional functionality this was considered too big a
can of worms to open.

Happens I'm the POC for 0-sized object extensions to C.  There has
so far been a distinct lack of interest in this area..

scjones@sdrc.UUCP (Larry Jones) (04/01/89)

In article <cYAd3My00UkaI1vvZr@andrew.cmu.edu>, bader+@andrew.cmu.edu (Miles Bader) writes:
> scjones@sdrc.UUCP (Larry Jones) writes:
> > And when handed a non-NULL pointer and a zero size, it acts like
> > free.  This behavior is required by the draft ANSI Standard.
> 
> Does it return NULL in this case (when it acts like free)?  If so, how
> extra-ordinarily convenient...

It's implementation defined -- the implementation is allowed to
return either a NULL pointer or a pointer to a zero-sized object
(although many people find that concept quite repugnant, that's
the way many existing implementations behave).

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"When all else fails, read the directions."

scjones@sdrc.UUCP (Larry Jones) (04/01/89)

In article <3229@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) writes:
> Gack.
> 
> The realloc((char*)0, size) thing was bad enough. What's this all
> about? [realloc(ptr, (size_t)0) === free(ptr)]
> 
> Stuff like this just makes it hard to port ANSII programs to
> old systems. Also makes it harder to convert an old system to ANSII.
> I can't think of any good reason to add such a silly spec. What am I
> missing?
> 
> Can anyone suggest a legitimate reason why they would want to do such
> a thing?

The idea is to avoid applications having to special case zero.
Thus, it should be possible to malloc for a size of zero, realloc
to or from a size of zero, and free something with a size of
zero.  Since C does not allow one to declare zero-size objects,
there was some objection to requiring implementations to allow
for dynamically created zero-size objects -- thus the compromise
of allowing pointers to zero-size objects to either be unique
pointers like all other object pointers, or all NULL at the
implementation's discretion.

Ease of porting to non-complying systems is NOT one of the goals
of the standard; ease of porting to COMPLYING systems IS.  Most
existing implementations I know of already meet this spec -- they
either return unique pointers for zero-size objects or consider
it an error and return NULL.  Since existing systems work both
ways, portable programs can't depend on a specific behavior and
so will work just fine with an ANSI implementation.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"When all else fails, read the directions."

antoine@alberta.UUCP (Antoine Verheijen) (04/01/89)

In article <9122@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes:
>
>
>gregg townsend reminds us of the pANS ``feature'' that malloc(0) returns NULL.
>can anyone provide the (or any) justification of this pointless stupid
>definition? i just love the idea that an initialised pointer is SOMETIMES
>indistinguishable from an uninitialised pointer.


Please note that a NULL pointer is not (necessarily) the same thing as an
uninitialized pointer. NULL is a very specific and legitimate value for
a pointer whereas an uninitialized pointer is, by definition, unpredictable,
its value usually being dependent on the system you're running under (unless
I've missed something new in the standard).

djones@megatest.UUCP (Dave Jones) (04/01/89)

From article <9962@smoke.BRL.MIL>, by gwyn@smoke.BRL.MIL (Doug Gwyn ):
> In article <3229@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>>Can anyone suggest a legitimate reason why they would want to do such
>>a thing?
> 
> I already did that.


Well excuuuusee ME!

The posting which I assume you refer to arived days after I posted
the above question.  In fact, somehow it got here *after* the 
"I already did that" posting (but in the same batch).

Might I suggest to everyone:

  1) if you are quoting are article, please include enough context 
  so that the reader can figure out what the quote
  is about -- (btw, I quoted the *entire* response above!) -- and

  2) if you refer to another article, or to a manual, or
  to a book or whatever, please identify it as best you can.

Thenkyewverymuch.

Now then.

This discussion is about the proposed ANSI behavior of malloc(0): namely
returning (char*)0.

I just now read the article alluded to above.

No sale.

Unless there are existing systems that behave in the proposed way -- 
(are there?) -- the new spec just breaks programs for no reason,
and perhaps too quietly.

I mean, if you really want a standard procedure that returns
(char*)0 when told to return a pointer to zero bytes, just define a
new one for Pete's sake!  Call it zzalloc, or something.

Looks to me like the only reasonable choices are

	1. Document the behavior as unpredictable; and
  
	2. Have malloc(0) return a pointer distinct from 0 and from all
	   other mallocked pointers, or else return 0 and set errno
	   if there is not enough memory available for the heap-overhead
	   of an empty packet. ("The set containing only the empty set 
	   is not empty," a famous Math professor used to be fond
           of reminding people.)


Given an xor, I prefer number 1, but I really would like to have
both!  That way, old programs will probably work, but I'll be warned
to check them over, and that they may not be portable.

Why is 1 better than the proposal?  Because otherwise somebody reading
the standard might be lulled into thinking that he is writing a portable
program when he's not. It is the ANSI-STANDARD, after all (ta-ta!).

Sidebar:

  I recall once, many many moons ago, writing a LISP-system in C.
  I was "young and easy, about the lilting house and happy as the grass
  was green", one might say, and I thought it was cool to allocate
  pointers to no bytes to represent t and nil. Made checking an S-
  expression for t-ness and nil-ness real quick...  and why allocate
  bytes when you're not going to use them, eh?  Okay, now maybe I know
  better,  but so what?

ka@june.cs.washington.edu (Kenneth Almquist) (04/01/89)

hascall@atanasoff.cs.iastate.edu (John Hascall) writes:
>     And what would you have malloc(0) return?   An Address?
What else?

>    ...which points to zero bytes of allocated storage?
At least zero bytes.

>    And would successive malloc(0) calls return the same pointer?
No.

>    (you're not using any heap with each call)
Yes you are, because malloc has to record the size of the allocated
block somewhere.

>    And then consider doing a "free" on such a pointer.
Makes as much sense as freeing any other pointer.

That's what existing UNIX malloc implementations do, and as I understand
it there is nothing in the ANSI C standard that prohibits this behavior.


In article <3810@geaclib.UUCP>, David suggests writing a program that
tests whether the realloc implementation is ANSI compliant, and using
it to conditionally compile a wrapper routine around realloc.  There is
no guarantee that the test program will work ("Testing can never show
the absense of bugs, only their presense."), although it should be
possible to write a wrapper routine that will work well enough in
practice.  Personally, I wouldn't bother; it seems simpler to just use
the wrapper routine all the time.
				Kenneth Almquist

andrew@alice.UUCP (Andrew Hume) (04/02/89)

	my request for an explanation of why anyone (especially pANS)
would give as silly an answer as 0 for malloc(0) generated a few useful
replies (thanks guy, brad, gwyn and kenneth) but a lot of
people were confused by my misstatement at the end. so let me rephrase:

	malloc(n) returning 0 is, to me, an error condition. that is,
i should pack up and go home. (of course i check malloc's return value).
But now, thanks to pANS, i first have to check if n==0. this is a pain
in the butt.

	the ONLY justification put forward is some stuff about zero-sized
objects (gwyn admits to being the point of contact). the only
point actually mentioned is devising semantics for zero-sized objects;
hascall derisively says ``And what would you have malloc(0) return?
An Address?''. paraphrasing kenneth's reply, ``gosh, yes, i would return an
address!''.
	lets get this straight; malloc has never said (at least until VERY recently)
that it returns a pointer to n bytes of storage. it has always said at least
n bytes of storage and the reason is clear if you look how most malloc's
are implemented; they almost always allocate an integral number of
machine words, rounding the actual request up. given that, what is
all the whining about? can't malloc(0) return a pointer to 1 (or 2 or 4)
bytes? of course, everyone would be happy now, wouldn't they?
and, innovative as it may be, 0 could revert to meaning 'I ran out of storage'
and we could even get rid of the peculiar special cases of giving
zero pointers to realloc. call me old-fashioned but 0 means
no pointer, end of list, you can stop here. don't let it become a
legitimate return value; just say no.

(and if anyone accuses me of flaming, let me say i didn't
actually say the decision was batshit).

bill@twwells.uucp (T. William Wells) (04/03/89)

In article <9964@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
: Happens I'm the POC for 0-sized object extensions to C.  There has
: so far been a distinct lack of interest in this area..

Somehow I missed that. How would one have discovered it?  When I
submitted my comments on the standard, I did ask that there be zero
sized arrays at the end of structures; I got a NAK.

Could you clue me in on what existing proposals there are on zero
sized objects? Few may be interested, but I am.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

gregg@ihlpb.ATT.COM (Wonderly) (04/03/89)

From article <9964@smoke.BRL.MIL>, by gwyn@smoke.BRL.MIL (Doug Gwyn ):
> In article <9122@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes:
>>gregg townsend reminds us of the pANS ``feature'' that malloc(0) returns NULL.
>>can anyone provide the (or any) justification of this pointless stupid
>>definition?
> 
> Sure.  malloc() either fails or it succeeds.  If it were required to
> succeed for a 0-sized allocation attempt, then additional semantics
> would have had to have been devised to deal with the 0-sized object
> pointed to by the returned non-null pointer.  For example, should
> a series of malloc(0) calls return distinct pointers?  Anyway, for
> the limited additional functionality this was considered too big a
> can of worms to open.

The use of malloc (0) may exist.  But I have always, and will always continue
to use

	if (nbytes == 0)
		nbytes = 1;

	if (ptr == NULL)
		ptr = (some cast) malloc (nbytes);
	else
		ptr = (some cast) realloc (ptr, nbytes);

When the sequence occurs a lot, I put it into a function.  For crissake,
this is not a "gee look at the benefits this feature provides" issue!  It
is a "gee look at how so many more portability issues are going to pop up"
issue!  And a stupid one at that!

Allocating a small amount of data to point a pointer into so that it is
non-null is going to save a large amount of code space and special case
code all through programs that deal with dynamic objects.

Changing one of the basic library routine interfaces is always a bad
idea, and it always will be!

-- 
Gregg Wonderly                             DOMAIN: gregg@ihlpb.att.com
AT&T Bell Laboratories                     UUCP:   att!ihlpb!gregg

oisin@cmtl01.UUCP (Oisin) (04/03/89)

in Article 131 of comp.std.c: gregg@ihlpb.ATT.COM (Wonderly)  says:
>From article <10170@bloom-beacon.MIT.EDU>, by scs@adam.pika.mit.edu (Steve Summit):
[ anecdote deleted ]
>> kept secret that realloc is supposed to behave gracefully at
>> a slightly special-cased boundary point: when handed a NULL
>> pointer and a nonzero size, it acts essentially as a malloc.
>
>I read the man page for realloc and it said nothing about this.  Is it
>not possible for you to type
>
>	if (ptr == NULL)
>		ptr = malloc (nbytes);
>	else
>		ptr = realloc (ptr, nbytes);
>
>or are you one of those people that assumes (*((char *)NULL) == 0) too?
[ more flame deleted ]

Pardon my ignorance, but if I'm wrong you can flame me too...
Does the draft not specify that whatever implementation of NULL is used, 
the compiler must guarantee that a ptr containing that implementation's
version of NULL must test as false?  (Notice I did not say it had to
BE false, just that the compiler must evaluate a logical test on it
as being false).  I'm don't write compilers or anything like that..
I'm just a "dumb end user" of C, but if my understanding is wrong, then
I and a lot of other programmers will have to "mend our ways".  I
stopped wasting my employers time with the redundant "== NULL" when
I read about that guarantee being in the standard.  Please correct
me if I am "bugging" my programs.

........................................................................
Oisin "Curly" Curtin -- uucp:uunet!attcan!cmtl01!oisin
Disclaimer- Opinions are my own.  CNR, AT&T and my wife don't want them.
........................................................................
Money is the root of all evil, and man needs roots

chris@mimsy.UUCP (Chris Torek) (04/03/89)

[flaming about realloc((char *)NULL) deleted]

In article <1196@cmtl01.UUCP> oisin@cmtl01.UUCP (Oisin) writes:
>Pardon my ignorance, but if I'm wrong you can flame me too...
>Does the draft not specify that whatever implementation of NULL is used, 
>the compiler must guarantee that a ptr containing that implementation's
>version of NULL must test as false?

Yes.  In standard-ese, a null pointer of any type must compare equal
to the integer constant zero and to the nil-pointer-to-void ((void *)0).
This has nothing to do with the flaming about

	realloc((char *)NULL, sz),  where sz > 0

nor that about

	malloc((size_t)0)
and	realloc(ptr, (size_t)0)

(The `correct' set of definitions---which is not the same as the pANS
set, but is fairly close; I can deal with the pANS version---appears
to me to be:

	malloc(sz) should return a unique pointer to at least sz bytes,
	or the value (void *)NULL if space is not available

	free((char *)NULL) should be a no-op, not an error

	realloc(ptr, sz) should `act like' free(ptr)+malloc(sz)+copy(old
	data, new location).  In particular, realloc(NULL) should act
	like malloc, and realloc(?, 0) should return a unique pointer to
	at least zero bytes.

This could be done in an ANSI-conformant environment with a small set
of wrapper functions.  Note that, with these definitions, malloc()
becomes unnecessary; it need not appear as a wrapper function.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

crossgl@ingr.com (Gordon Cross) (04/03/89)

In article <3229@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>
>The realloc((char*)0, size) thing was bad enough. What's this all
>about?
>Can anyone suggest a legitimate reason why they would want to do such
>a thing?

Yes!!  Imagine a situation wherein you are dynamically adjusting your memory
requirements (both up and down) to hold data which may grow and shrink in
its storage requirements.  This behavior eliminates special handling of the
boundary case when the size periodically goes to zero!!  I've desired this
behavior many times and I solved it with:

char *myrealloc (ptr, size)

char     *ptr;
unsigned  size;
{
  if (!ptr)
    return malloc (size);
  if (!size) {
    free (ptr);
    return 0;
  }
  return realloc (ptr, size);
}

I am VERY pleased that ANSI choose to require this behavior...
-- 

Gordon Cross             UUCP:      uunet!ingr!crossgl     "all opinions are
111 Westminister Way     INTERNET:  crossgl@ingr.com        mine and not those
Madison, AL 35758        MA BELL:   (205) 772-7842          of my employer."

crossgl@ingr.com (Gordon Cross) (04/03/89)

In article <9122@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes:
}
}gregg townsend reminds us of the pANS ``feature'' that malloc(0) returns NULL.
}can anyone provide the (or any) justification of this pointless stupid
}definition?

Yes, a pointer to something of zero size takes up NO space!!!  You would be
able to increase this size later with the (ANSI) realloc...  (ain't life great)

-- 

Gordon Cross             UUCP:      uunet!ingr!crossgl     "all opinions are
111 Westminister Way     INTERNET:  crossgl@ingr.com        mine and not those
Madison, AL 35758        MA BELL:   (205) 772-7842          of my employer."

crossgl@ingr.com (Gordon Cross) (04/03/89)

In article <9132@alice.UUCP> andrew@alice.UUCP (Andrew Hume) writes:
>
>	malloc(n) returning 0 is, to me, an error condition. that is,
>i should pack up and go home. (of course i check malloc's return value).
>But now, thanks to pANS, i first have to check if n==0. this is a pain
>in the butt.

Yes, it is.  I've always wanted behavior similiar to an "out-of-memory"
signal that I could trap to let me know when there is no more memory.  So
much so in fact, I wrote my own malloc that lets me set things up to have
a function called whenever an out-of-memory condition occurs.  Regrettably
to the best of my knowlegde, the pANS does not address this issue...
-- 

Gordon Cross             UUCP:      uunet!ingr!crossgl     "all opinions are
111 Westminister Way     INTERNET:  crossgl@ingr.com        mine and not those
Madison, AL 35758        MA BELL:   (205) 772-7842          of my employer."

peter@ficc.uu.net (Peter da Silva) (04/03/89)

  [ malloc(0) -> NULL is a bug]
In article <934@atanasoff.cs.iastate.edu>, hascall@atanasoff.cs.iastate.edu (John Hascall) writes:
> And what would you have it return?   An Address?

Yes.

> ...which points to zero bytes of allocated storage?

Yes.

> And would successive malloc(0) calls return the same pointer?

No.

> (you're not using any heap with each call)

Yes you are. 4-8 bytes depending on memory model.

> And then consider doing a "free" on such a pointer.

Sure.

malloc(NULL) -> NULL is an optimisation better performed by the programmer.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

guy@auspex.auspex.com (Guy Harris) (04/04/89)

>>I read the man page for realloc and it said nothing about this.  Is it
>>not possible for you to type
>>
>>	if (ptr == NULL)
>>		ptr = malloc (nbytes);
>>	else
>>		ptr = realloc (ptr, nbytes);
>>
>>or are you one of those people that assumes (*((char *)NULL) == 0) too?
>[ more flame deleted ]
>
>Pardon my ignorance, but if I'm wrong you can flame me too...
>Does the draft not specify that whatever implementation of NULL is used, 
>the compiler must guarantee that a ptr containing that implementation's
>version of NULL must test as false?

Huh?  What does that have to do with any of this?  The draft does
specify that

	if (x)

is equivalent to

	if (x != 0)

and that, at least for "x" of pointer type, that is in turn equivalent
to

	if (x != NULL)

but in no way does the draft require that

	*((char *)NULL) == 0

and a damn good thing that is - some implementations cause programs that
illegally attempt to dereference the null pointer to blow up, so that
bugs of that sort are caught....

If *you* want to write

	if (p)

rather than

	if (p != NULL)

go ahead; both are equally legal C, and while the "!= NULL" may be
redundant in some sense, at least some of us find that

	if (p != NULL)

easier to read than

	if (p)

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/04/89)

In article <3240@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>Why is 1 better than the proposal?  Because otherwise somebody reading
>the standard might be lulled into thinking that he is writing a portable
>program when he's not. It is the ANSI-STANDARD, after all (ta-ta!).

I think that would indicate confusion about the use of the C standard
that needs to be straightened out anyway.  The (p)ANS is not intended
to document a "lowest common denominator" of existing C implementations.
It IS intended to document an interface that can be relied on for any
implementation that is advertised as ANSI C standard conforming.  How
to cope with non-standard implementations is a proper topic for courses
in C programming, but it's not directly the business of the standard.

djones@megatest.UUCP (Dave Jones) (04/04/89)

From article <9132@alice.UUCP>, by andrew@alice.UUCP (Andrew Hume):
> what is
> all the whining about? can't malloc(0) return a pointer to 1 (or 2 or 4)
> bytes? of course, everyone would be happy now, wouldn't they?

Hear! Hear!

Indeed, most implementations could actually return a valid pointer to
ZERO bytes, if they wanted to!

Yep.  Typically a pointer to a heap-packet is the machine-address of the
memory just after a heap-packet HEADER, which the heap routines use
to keep books.  Since no two heap-packets have the same headers, no
two heap-packets have the same heap-packet pointer.  This remains
true even if no memory beyond the header is actually reserved.

In practice, a heap-packet-pointer-to-nothing would typically
be the machine address of another heap-packet-header.  We dare not 
dereference it, but so what?  It is always an error to use a
heap-packet-pointer to index as much as heap-packet-size bytes into the 
heap-packet. (Doing so usually gets you into another heap-packet-header,
or another heap-packet, and can keep you awake debugging all night
and most of the next day, so don't DO that!)

Ego, with a pointer to zero bytes, it is an error to index even zero-bytes
beyond it.  That is to say, the pointer-to-nothing is good only for
comparing for equality with similarly typed pointers.

No problem.

Maybe on a Prevert-2000, that keeps different kinds of pointers in
different shapes of mayonaise jars, you would have to allocate a byte
or four of memory.  Okay. Fine.

Ain' no deal, Home!

frank@zen.co.uk (Frank Wales) (04/04/89)

In article <1196@cmtl01.UUCP> oisin@cmtl01.UUCP (Oisin) writes:
>in Article 131 of comp.std.c: gregg@ihlpb.ATT.COM (Wonderly)  says:
>>or are you one of those people that assumes (*((char *)NULL) == 0) too?
>
>Pardon my ignorance, but if I'm wrong you can flame me too...
>Does the draft not specify that whatever implementation of NULL is used, 
>the compiler must guarantee that a ptr containing that implementation's
>version of NULL must test as false?

[just a singe] Gregg was actually bemoaning the extremely fragile assumption
that dereferencing a NULL pointer yields 0, probably the commonest single
pain in the arse to those who would port other people's programs.
--
Frank Wales, Systems Manager,        [frank@zen.co.uk<->mcvax!zen.co.uk!frank]
Zengrange Ltd., Greenfield Rd., Leeds, ENGLAND, LS9 8DB. (+44) 532 489048 x217 

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/05/89)

In article <3255@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>... with a pointer to zero bytes, ...
>No problem.

You haven't thought out all the ramifications of officially permitting
0-sized objects in C.  That's not to say that the problems are insoluble,
but they are there and must be dealt with if you're going that direction.

jss@hector.UUCP (Jerry Schwarz) (04/07/89)

In article <3240@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>
>This discussion is about the proposed ANSI behavior of malloc(0): namely
>returning (char*)0.
>

Its really about a rumor about the standard.  The actual proposed
standard says (4.10.3)

        "If the size of the space requested is zero, the behavior is
        implementation-defined; the value returned shall be either a
        null pointer or a unique pointer."

In other words the status of malloc(0) is exactly the same as it is
now.  In some implementations it will return a null pointer and in
others it won't.  A program that assumes either behavior may be
conforming but not strictly conforming (i.e. not maximally portable).


Jerry Schwarz
AT&T Bell Labs, Murray Hill

pas@unhd.unh.edu (Paul A. Sand) (01/30/91)

In article <23975:Jan2516:36:5891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Some versions of realloc() return the original pointer rather than 0 if
>they run out of memory. So you have to code the malloc()/bcopy()/free()
>sequence yourself if you want error checking.

Other posters have pointed out that such realloc()'s are seriously
broken, but I wonder how many versions "some versions" actually are.  A
brief check of my portability references (Jaeschke's _Portability and
the C Language_, Rabinowitz's and Schaap's _Portable C_, 1st and 3rd
editions of Harbison & Steele) doesn't turn up any warnings about such
behavior. (And these folks seem to warn about *very* unlikely things.)

But as long as I'm reading, I did notice a howler in Jaeschke's text,
on page 320:

	You should ALWAYS use realloc as follows:

	ptr = realloc(ptr, new_size);

Emphasis is Jaeschke's. Even a tyro like me can recognize that you
are in big trouble if (a) the realloc() fails, (b) ptr is your only
access to the block, and (c) you had something important there.
-- 
-- Paul A. Sand                |
-- University of New Hampshire | I ain't here on business, baby.
-- uunet!unhd!pas              | I'm only here for fun.
-- pas@unhd.unh.edu            |

LSC@SLACVM.SLAC.STANFORD.EDU (04/23/91)

Hi,

     In the ANSI standard, p 155 line 23, it says:

     "If the space cannot be allocated, the object pointed to by ptr is unchang
unchanged."

     Does this mean that one has no means of checking the success or failure
of the operation? Does one have to resort to errno?

                                        Thanks
                                                Lou


Lou Sanchez-Chopitea                   InterNet: lsc@slc.slac.stanford.edu
Control Systems Programmer             BitNet:   lsc@slacslc
Stanford Linear Accelerator Center     DecNet:   45258::lsc or slc::lsc

gwyn@smoke.brl.mil (Doug Gwyn) (04/23/91)

In article <91112.102011LSC@SLACVM.SLAC.STANFORD.EDU> LSC@SLACVM.SLAC.STANFORD.EDU writes:
>     Does this mean that one has no means of checking the success or failure
>of the operation? Does one have to resort to errno?

No -- when one of the allocation functions fails, it returns a null pointer.

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/23/91)

In article <91112.102011LSC@SLACVM.SLAC.STANFORD.EDU> LSC@SLACVM.SLAC.STANFORD.EDU writes:

>     In the ANSI standard, p 155 line 23, it says:
I have the Dec. 1988 draft and it's page 156 there.

>     "If the space cannot be allocated, the object pointed to by ptr is unchang
>unchanged."
>     Does this mean that one has no means of checking the success or failure
>of the operation? Does one have to resort to errno?

No.  It only means that ptr still points to the object and the object is
not changed.  The value of the actual parameter did not get changed anyway
because C has call-by-value semantics.  The quoted line only says that the
value still points to the same object.

Failure is still indicated by returning a null pointer as the function's
returned value.  This is on page 155 in the Dec. 1988 draft, lines 17-18.
This paragraph applies to all memory allocation routines.

I cannot find any guarantee that errno gets set when errors occur in
memory allocation routines.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

barmar@think.com (Barry Margolin) (04/23/91)

In article <1991Apr23.001451.14900@tkou02.enet.dec.com> diamond@jit345.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>In article <91112.102011LSC@SLACVM.SLAC.STANFORD.EDU> LSC@SLACVM.SLAC.STANFORD.EDU writes:
>>     "If the space cannot be allocated, the object pointed to by ptr is unchang
>>unchanged."
>Failure is still indicated by returning a null pointer as the function's
>returned value.

What this *does* mean is that the common practice of

	fooptr = realloc (fooptr, newsize);

results in a memory leak whenever realloc() returns a null pointer.  Of
course, when realloc() fails, it's probably because you're out of memory,
so this one unfreeable allocation probably isn't a problem.  However, the
point is that one *should* write

	new_fooptr = realloc (fooptr, newsize);
	if (new_fooptr) {
	    fooptr = new_fooptr;
	}
	else /* report the error */
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

jimp@cognos.UUCP (Jim Patterson) (04/23/91)

In article <91112.102011LSC@SLACVM.SLAC.STANFORD.EDU> LSC@SLACVM.SLAC.STANFORD.EDU writes:
>Hi,
>     In the ANSI standard, p 155 line 23, it says:
>
>     "If the space cannot be allocated, the object pointed to by ptr is unchang
>unchanged."
>
>     Does this mean that one has no means of checking the success or failure
>of the operation? Does one have to resort to errno?

Check 4.10.3 (page 155 line 17 in mine; I think yours is different). It
says

   If the space cannot be allocated, a null pointer is returned.

So, hang on to your original pointer. realloc shouldn't free the space
it points to if it fails, but it may appear to because it will return
a null pointer value.

-- 
Jim Patterson                              Cognos Incorporated
UUCP:uunet!mitel!cunews!cognos!jimp        P.O. BOX 9707    
PHONE:(613)738-1440 x6112                  3755 Riverside Drive
                                           Ottawa, Ont  K1G 3Z4

gwyn@smoke.brl.mil (Doug Gwyn) (04/24/91)

In article <1991Apr23.045937.178@Think.COM> barmar@think.com (Barry Margolin) writes:
>... the common practice of
>	fooptr = realloc (fooptr, newsize);
>results in a memory leak whenever realloc() returns a null pointer.

People who would write that code would probably also fail to test for a
null pointer being returned anyway, so they have a bigger problem than
memory leaks.  (Your suggested solution is fine.)

bjoern@drdhh.hanse.de (Bjoern Kriews) (04/26/91)

From article <91112.102011LSC@SLACVM.SLAC.STANFORD.EDU>, by LSC@SLACVM.SLAC.STANFORD.EDU:
>      "If the space cannot be allocated, the object pointed to by ptr is unchang
> unchanged."
> 
>      Does this mean that one has no means of checking the success or failure
> of the operation? Does one have to resort to errno?

"If it cannot reallocate the memory, it returns NULL"

Hmm, what to say, he DID RTFM  :-)

Greetings,
	Bjoern
	

---
bjoern@drdhh.hanse.de = Bjoern Kriews / Stormsweg 6 / 2000 Hamburg 76 / FRG
"gaaga mahwe Bjoern urgl ufzae Turbo-C bnub"     (J. Willamowius)