DASCHBACH@CHEMISTRY.UTAH.EDU (06/15/89)
/* ** gnu-cc-bug.c ** ** This program will execute the print statement at line 171 for n >= 7. ** With this example the return should allways be 1.00 and the print ** statement should never be reached. When the print statement is ** executed the *correct* value of 1.00 appears. This indicates to ** me a timing problem of some sort, I have seen similar things on ** other machines in FORTRAN. ** ** If the return type for 'trivial_func' is changed to 'void' or to 'int' ** no error obtains. If the return value for 'trivial_func' is used, ** eg. 'ytemp = (*derivs)(1.0,&yout);', then no error obtains. ** ** If the call to '(*derivs)' outside of the loop is asigned to ** ytemp, and not the call inside, then the error obtains for ** n >= 8. ** ** It is my understanding that ignoring a return from a function is ** allowed, certainly this is common practice for many library functions ** returning 'int'. ** ** I understand that the returning of a double which is unused is not ** good practice, and is allmost certainly slower, but this code is a ** massive reduction of the code in which the bug was found. ** ** This code runs as expected when compiled with the Sun cc on the ** Sun 386i/250 and the Sun 4/280, both running SunOS 4.0.1. Also works ** on the Multiflow Trace TRACE/UNIX 4.1.5, and Microsoft C 5.1 on a PC ** ** If ignoring the return on a function called through a pointer is not ** allowed then I am sorry to trouble you. However I have been unable to ** find any refernce which states this. Certainly examples can be found ** where the return type is int and it is ignored. ** ** define NO_BUG1 to assign the return value ** define NO_BUG2 to use return type int ** defint NO_BUG3 to use return type void ** ** Info: ** ** GNU CC version 1.35 ** compiled using 'gcc -g -o bug gnu-cc-bug.c' ** | 'gcc -g -o no_bug1 -DNO_BUG1 gnu-cc-bug.c' ** | 'gcc -g -o no_bug2 -DNO_BUG2 gnu-cc-bug.c' ** | 'gcc -g -o no_bug3 -DNO_BUG3 gnu-cc-bug.c' ** ** tm: tm-sun386i.h ** md: i386.md ** ** Machine: Sun 386i/250 ** OS: SunOS 4.0.1 ** ** I am using the Sun assembler and linker. I have been able to get GNU CC ** working with the GNU as and ld, but any program compiled with this setup ** crashes 'segmentaion fault (core dump)'. ** It appeared to me that with the hastles of COFF object format etc. ** and no debugging support, it was easiest to use the Sun assembler ** and loader. I have had no problems running dbx with this arrangement. ** ** Thanks. ** John L. Daschbach ** Department of Chemistry ** University of Utah ** Salt Lake City, UT 84112 ** ** daschbach@chemistry.utah.edu */ /*-------------------------------------------------------------------------*/ #include <stdio.h> /*-------------------------------------------------------------------------*/ extern int main(); extern void mid_pnt(); #if defined(NO_BUG1) extern double trivial_func(); #elif defined(NO_BUG2) extern int trivial_func(); #elif defined(NO_BUG3) extern void trivial_func(); #else extern double trivial_func(); #endif /*-------------------------------------------------------------------------*/ double yout=0.0; int nstep=100; /*-------------------------------------------------------------------------*/ int main(argc,argv) int argc; char **argv; { mid_pnt(nstep,&yout,trivial_func); exit(0); } /*-------------------------------------------------------------------------*/ /* ** ** trivial_func() ** ** This trivial function allways returns 1.0 */ #if defined(NO_BUG1) double #elif defined(NO_BUG2) int #elif defined(NO_BUG3) void #else double #endif trivial_func(yout) double *yout; { *yout = 1.0; #if defined(NO_BUG2) return(1); #elif defined(NO_BUG3) return; #else return( *yout ); #endif } /*-------------------------------------------------------------------------*/ /* ** mid_pnt() ** ** */ void mid_pnt(nstep,yout,derivs) int nstep; double *yout; #if defined(NO_BUG1) double (*derivs)(); #elif defined(NO_BUG2) int (*derivs)(); #elif defined(NO_BUG3) void (*derivs)(); #else double (*derivs)(); #endif { int n; #if defined(NO_BUG1) double ytemp; ytemp = (*derivs)(yout); #else (*derivs)(yout); #endif for( n = 2; n <= nstep; n++ ) { #if defined(NO_BUG1) ytemp = (*derivs)(yout); #else (*derivs)(yout); /* note that *yout will *allways* be 1.00 */ #endif /* the next section executes for n >= 7 on the sun386i/250 however in the print statement *yout is *allways* 1.00. the next statement can be changed to any value > 0.0 and the if clause will be true. A test for equality == 0.0 will also evaluate to TRUE */ if ( *yout < 1.0 ) printf("mid_pnt() ERROR n %4d yout %le\n",n,*yout); } return; }