[gnu.gcc.bug] NeXT alloca

cpenrose@ucsd.edu (Christopher Penrose) (01/24/91)

--text follows this line--
Oh no! Not again!

Ok.  I spoke too soon.  I have discovered what appears to be a
alloca() bug within NeXT 2.0 gcc 1.36.  The problem could also be a
bug with ld, as the release notes have indicated that it was
completely overhauled.  Basically, arbitrary arrays allocated by
malloc() lose their integrity -- the addresses that malloc() provides
change without program assignment.  These bugs are very pernicious; I
have experienced them with Sun's cc.  I have a remedy; but it is not a
fix.  I will first summarize my experience.  I could have saved my
terminal session with gdb, but I really didn't feel like playing with
it anymore.  It was also extremely big.

I have several signal processing programs which share a similar
program structure.  Buffered input is read from the standard input,
processed, and output through the standard output.  After playing the
new include file dance, I managed to get most of these programs to
work.  However, one particular program, that shares most of the
functions of the others, persistently crashed from segmentation
violations.  Using gdb, I found a ridiculous integer pointer index.
It took a while to trace the index (which had worked through many
earlier iterations of the function) back to two NaN valued floats that
were obtained by the fread() function.  I checked the data fread() was
reading -- the entire segment (32 floats) were all zeros.  Of the 32,
fread() obtained two NaN values.  Also, earlier iterations of the
function successfully read buffers containing only zero valued floats.
Very scary -- how can the machine run with system call bugs like
these?  Well, it didn't take me long to conclude that UNIX could not
run with a bug in fread().  I then discovered that the memory
locations of my input array had changed mysteriously.  Anyway, this
behavior reminded me all too much of some of the games I had to play
with Sun's malloc() routines.  I had a few unused functions linked
with the program, so I removed them.  Then I grabbed my universal
malloc() remedy: space().  It saved me from the Sun malloc() hoax --
and it is painfully simple:

#define allc_min 4096

char *space( sz, obsz )
int sz, obsz;
{
    char	*p;

    if ( (sz * obsz) < allc_min ) {
	if ( (p = (char *) malloc( allc_min )) == NULL ) {
	    fprintf(stderr,"No Memory!\n");
	    exit(-1);
	}
    }
    else {
	if ( (p = (char *) malloc( sz * obsz )) == NULL ) {
	    fprintf(stderr,"No Memory!\n");
	    exit(-1);
	}
    }
    return p;
}

space() allocates memory normally if the requested size is greater or
equal to the threshold allc_min.  If the requested size is less than
allc_min, then size allc_min is allocated instead.  I tend to choose
powers of two for allc_min.  I was considering a space() function that
allocated the next power of two after size, if size were greater than
the threshold.  This was unnecessary, as this space() function
remedied the emphemeral memory hoax. 

I had hoped that I wouldn't run into these problems again.  Oh well, 
I seem to be able to live with them.
 

Christopher Penrose
jesus!penrose