[comp.sources.d] gnu egrep - realloc of 0 bytes caused failure: Memory exhausted

dennis@rlgvax.UUCP (Dennis.Bednar) (02/15/89)

The GNU version of egrep failed to work on a CCI 6/32
running Unix SV.  The bug was traced to the fact that
realloc(p, n) was being called with n==0, given the
command line "grep abc".  I did not have time to track
down the gory details as to why realloc was being called
with 0, nor why it supposedly works on other machines
(assuming that realloc is called with 0 on other machines).

To fix the problem temporarily, in dfa.c, in the function
xrealloc(), change:
  ptr_t r = realloc(p, n);
to
  ptr_t r = realloc(p, ( n ) ? n : 50);
so that a dummy 50 byte realloc would be done if the size
were zero.  Without the change, our realloc() library routine
was returning char *NULL, causing a "Memory exhausted" message.

Comments from the authors?

-dennis
-- 
FullName:	Dennis Bednar
UUCP:		{uunet|sundc}!rlgvax!dennis
USMail:		CCI; 11490 Commerce Park Dr.; Reston VA 22091
Telephone:	+1 703 648 3300

chasm@killer.DALLAS.TX.US (Charles Marslett) (02/16/89)

In article <1114@rlgvax.UUCP>, dennis@rlgvax.UUCP (Dennis.Bednar) writes:
> The GNU version of egrep failed to work on a CCI 6/32
> running Unix SV.  The bug was traced to the fact that
> realloc(p, n) was being called with n==0, given the
> command line "grep abc".  I did not have time to track
> down the gory details as to why realloc was being called
> with 0, nor why it supposedly works on other machines
> (assuming that realloc is called with 0 on other machines).

In porting (bringing up) gnugrep under MSDOS I ran across the fact that
there is a macro at the beginning of regex.c (or perhaps dfa.c (?)) that
did a realloc with a size of "1<<16", a very bad number of bytes to
specify if your integers are 16 bits long.  I changed it to 1<<14, and
all is now functional!  Does the CCI 6/32 perhaps use 16-bit integers?

> -dennis

===========================================================================
Charles Marslett
STB Systems, Inc.  <== Apply all standard disclaimers
Wordmark Systems   <== No disclaimers required -- that's just me
chasm@killer.dallas.tx.us

mike@thor.stolaf.edu (Mike Haertel) (02/17/89)

I found out about the realloc problem about the same time grep was
posted (maybe a few days before) . . . it is fixed in the next version,
and there are a few other improvements.  When I finish it I will send
a diff to comp.sources.unix.

On an unrelated note, grep will not work on a Sun 3 if compiled with
-O2 or higher optimization, or on a Sun 4 with -O (which turns out to
be the same as -O2).  This is definitely a bug of Sun's compiler.
Use gcc . . .

	Mike Haertel
	mike@wheaties.ai.mit.edu

guy@auspex.UUCP (Guy Harris) (02/17/89)

>nor why it supposedly works on other machines
>(assuming that realloc is called with 0 on other machines).

Some implementations of C permit you to call "malloc" or "realloc" with
a size of 0.  Others do not.  Since many implementations return e.g. a
pointer to the "data" portion of a structure such as:

	+------------------+
	| memory allocator |
	|   header stuff   |
	+------------------+
	|       data       | <- pointer points here
	.		   .
	.		   .
	.		   .
	+------------------+

it *is* possible, in those implementations, to have "malloc"/"realloc"
return something if you ask it for zero bytes.  Since "realloc" can grow
or shrink a block, it's not necessarily useless to ask for 0 bytes of
storage; you can start out with a zero-byte block and grow it as
necessary, without having to remember that you asked for 1 byte (or
storage unit of whatever sort; e.g.  array element, if you're stuffing
an array into it) when you first got it.

In some ways, it's the moral equivalent of a zero-length array in
something such as:

	struct message {
		int	length;
		char	data[0];
	};

where an N-byte message would require "sizeof (struct message) + N" bytes.

Reasons have been given why zero-length arrays might not be a good idea
(attempts to drag me into a debate on the merits of zero-length arrays
will produce no responses, just a fair bit of annoyance - I've steered
clear of that debate).  Some of those reasons might apply to zero-length
mallocated blocks, as well.  Some implementations do, in fact, forbid
them; the May 13, 1988 ANSI C draft says that an implementation can do
one of two things when asked to allocate a zero-length block of storage:

	1) return a null pointer;

	2) return a "unique pointer", which presumably means "return a
	   pointer to something that can be treated as a zero-length
	   block of storage" - i.e., you can't store anything into it,
	   but you can ask "realloc" to grow it and can ask "free" to
	   free it.

The SVID currently says it must return a null pointer.  However, the
standard "malloc" in S5 (which isn't SVID-compliant - only the one in
"-lmalloc" is SVID-compliant) does 2); I seem to remember that at least
one version of "dc" depended on 2) working. 

Bottom line: if you want your code to be portable, make sure you don't
call "malloc", "realloc", etc. with a size of 0.

fkk@altger.UUCP (Frank Kurt Kaefer) (02/17/89)

In article <1114@rlgvax.UUCP> dennis@rlgvax.UUCP (Dennis.Bednar) writes:
~The GNU version of egrep failed to work on a CCI 6/32
~running Unix SV.  The bug was traced to the fact that
~realloc(p, n) was being called with n==0, given the
~command line "grep abc".  I did not have time to track
~down the gory details as to why realloc was being called
~with 0, nor why it supposedly works on other machines
~(assuming that realloc is called with 0 on other machines).
~
~-dennis
~-- 

Hiya!

I have the same problem under OS-9/68000. I think the fix by dennis can
only be a tenmporarily solution but it is nevertheless useful.
Some comments from the authors ?

Frank (fkk@stasys.UUCP ...!pyramid!tmpmbx!doitcr!stasys!fkk)