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