AER7101@TECHNION.BITNET (Zvika Bar-Deroma) (06/11/88)
Hello, I have some questions concerning a bug (or as I call it, when it bares the name of a big manufacturer, an undocumented feature..). I ran the following program on several machines. There is "some problem" with the program, as in the subroutine, an attempt is made to redefine a constant. Naively enough, I expected to get a reasonably clear message in English, (not HEX location of unknown registers..), just as the following will: * this produces "clear" message: PARAMETER ( I=5) I=1 END The message you get follows: *ERR* EQ-02 line 2, column 7, cannot assign value to expression (That's WATFOR77's compiler, one could think of something better like: "trying to redefine a constant", which I saw somewhere, but even that's good enough..). Now try to run the following program. Do NOT allocate files (if possible with your system) and check the following: 1. On which unit it printed 'THIS SHOULD BE PRINTED ON UNIT 1' ? 2. What is the value of I printed on the default output unit ? CALL TRY ( 1 ) WRITE (1,*) 'THIS SHOULD BE PRINTED ON UNIT 1' I=1 WRITE (*,*) ' I (SHOULD BE 1) = ',I STOP END SUBROUTINE TRY ( KUKU ) KUKU = 8 RETURN END Following are the results of some compilers (refer to the questions): compiler/machine unit # I comments ************************ ****** * ******** IBM VS FORTRAN 2.2.0 8 1 OPT(2) causes I to be 8 .. IBM VS FORTRAN 1.4.1 8 8 WATFOR77 2.5 1 1 CDC/NOS FTN5 8 1 CDC/ NOS/VE FORTRAN runtime err: "ACCESS VIOLATION" + HEX location (when run with full debug causes the cursor to point at the "KUKU=8" line, in addition to the ACCESS VIOLATION error msg. ) VAX/VMS FORTRAN runtime err: "ACCESS VIOLATION" + HEX location WATFIV err. msg.: ***ERROR*** SUBPROGRAM TRY REDEFINES A CONSTANT, EXPRESSION, DO-PARAMETER OR ASSIGNED GOTO INDEX ( ARGUMENT NUMBER 1) PROGRAM WAS EXECUTING LINE 1 IN ROUTINE M/PROG WHEN TERMINATION OCCURED Unfortunately, WATFIV is FORTRAN 4 .... How does your compiler execute this program ? Can anyone tell me if/what the ANSI standard "says" to such a situation? How about the 8x draft ? (Of course, my program is a small demonstration of a problem that can be serious, as happened to a user here with a program a few thousand statements long, producing inexplicable results). Regards, Zvika Bar-Deroma dept. of Aeronautical eng. Technion, Haifa, Israel BITNET : AER7101@TECHNION INTERNET : AER7101%TECHNION.BITNET@cunyvm.cuny.EDU DOMAIN NAMING : AER7101@TECHNION.TECH.AC.IL UUCP : .....!ucbvax!aer7101@technion.bitnet CSNET : aer7101@technion.bitnet
mcdonald@uxe.cso.uiuc.edu (06/12/88)
> CALL TRY ( 1 ) > WRITE (1,*) 'THIS SHOULD BE PRINTED ON UNIT 1' > I=1 > WRITE (*,*) ' I (SHOULD BE 1) = ',I > STOP > END > SUBROUTINE TRY ( KUKU ) > KUKU = 8 > RETURN > END This is the classic expression of a common stupid Fortran bug. It is not legal Fortran for a subroutine to redefine the value of a constant or expression. It doesn't matter WHAT a given compiler does with it: it is an illegal construct. It is up to the programmer to write correct programs. Fortran compilers are required to give correct output with correct programs. If you feed them a program with a bug in it, the resulting output is "undefined" , which means essentially anything is "correct" behaviour of the compiler.
smryan@garth.UUCP (Steven Ryan) (06/13/88)
This is a long standing feature of Fortran. All parameters are passed by reference, so the address of the constant 1 is passed. The subroutine does not know this is constant--it is considerred the programmer's responsibilty. In some systems the constant is in a readonly page so that attempts to store into it cause an access violation. In some systems the io is translated into calls with the unit being passed by value (hidden protocols need not be conforming). In some systems constants used in expressions are handled by load immediate instructions so that each use of a constant is distinct. In other systems all uses of a constant map into the same memory location. Make it simple--not simplistic. sm ryan
bill@hcx2.SSD.HARRIS.COM (06/13/88)
/* Written 8:22 am Jun 11, 1988 by AER7101@TECHNION.BITNET.UUCP in hcx2:comp.lang.fortran */ /* ---------- "fortran problem" ---------- */ > Hello, > I have some questions concerning a bug (or as I call it, when it > bares the name of a big manufacturer, an undocumented feature..). > I ran the following program on several machines. There is "some problem" > with the program, as in the subroutine, an attempt is made to redefine > a constant. > Naively enough, I expected to get a reasonably clear message in English, > > Can anyone tell me if/what the ANSI standard "says" to such a situation? > How about the 8x draft ? /* End of text from hcx2:comp.lang.fortran */ The Standard says (Section 15.9.2), "Actual arguments may be constants, symbolic names of constants, function references, expressions involving operators, and expressions enclosed in parentheses if and only if the associated dummy argument is a variable that is not defined during execution of the referenced external procedure." The 8x draft says essentially the same thing, in quite a different way, but it also (at least, at the moment) provides you with INTERFACE blocks that can declare the INTENT of each argument, giving the compiler the opportunity of giving a more meaningful error message in this situation. If you choose not to use INTERFACE, though, you're back to F77. As has been pointed out about a zillion times, the Standard says absolutely nothing about what errors the FORTRAN processor (compiler, linker, loader, et al.) must give for programs that violate some restriction other than a syntax rule. It says only what is a standard-conforming program; non-conforming programs may or may not be detected. If they are detected, the Standard says nothing about what the error message (if any) must say. Bill Leonard (member, X3J3) Harris Computer Systems Division 2101 W. Cypress Creek Road Fort Lauderdale, FL 33309 bill@ssd.harris.com or bill%ssd.harris.com@eddie.mit.edu
cdb@hpclcdb.HP.COM (Carl Burch) (06/14/88)
Unfortunately, any such program is not standard-conforming, and the standard therefore says exactly nothing about its required behavior. The relevant passage of the F77 standard is paragraph 15.9.2 on page 15-16 : "Actual arguments may be constants ... if and only if the associated dummy argument is a variable that is not defined during execution of the referenced external procedure." The Fortran 8x draft standard has similar words, and is quite likely to retain them in light of the F8x Prime Directive - to be 100% F77 compatible. There are some tools that try to find such problems - see the previous notestrings on Fortran lint. I don't know if they mentioned MAT from SAIC, or flint from Programming Research Ltd in England. I haven't used either one, but they're both made by nice guys that know more about the problem than I do. As for your general implication on the quality of compilers that cause this sort of problem, I wish you hadn't mentioned the specific companies you compared - I could be somewhat more candid in the abstract. As it is, I will just report that the problem you cite was used as a horror story in the compiler-writing class I took at Purdue in 1981 - with the professor's opinion that this story is so famous that nobody would ever do it "wrong" again. Silly him. Actually, after a similar conversation with a couple HP customers at a users group conference I found to my dismay that HP still has one compiler (F7x on the HP1000) that also allows constants to change value this way. So (as the saying goes) "Let's be CAREFUL out there!" - Carl Burch cdb%hpda@hplabs.HP.COM HP Fortran Team
hirchert@uxe.cso.uiuc.edu (06/16/88)
I'd like to make a few more observations on the issue of changing constants in Fortran: 1. In the most general case, detection _requires_ run-time checks. Consider the following procedure: SUBROUTINE SUB(X,ICODE) SAVE XX IF(ICODE.EQ.0)THEN XX=X ELSE X=XX ENDIF END This routine is correct (according to the rules of Fortran), as long as ICODE has the value 0 for each call to SUB where the actual argument corresponding to X is not something that can be assigned to. In general, we will not know the value of ICODE until run-time (e.g. it may be read in), so no static analysis (whether by the compiler, the linker, or a separate "lint" program) can say definitely whether or not this program is correct. This is not to say that static analysis is useless. Static analysis can recognize that there is the possibility for error in this procedure and can recognize when the erroneous statement is unconditional. 2. Thus, in the general case, checking for this error (or protecting a program from the effects of this error) is never entirely without run-time cost. The closest one can come to no cost is when the hardware does the checking (as when constants are stored in write-protected memory). Unfortunately, the error messages for hardware detected errors are often cryptic and/or difficult to relate to one's Fortran error. If hardware detection is either unavailable or undesirable, then the compiler must generate extra code, either to check for the occurrence of this error or to copy constants to storage that can be modified without hurting anything. 3. In turn, this means that it is not necessarily "wrong" to allow programs to commit this error. It depends on whether it is more important to you (and your customers) to detect (or protect the program from) errors or to achieve maximum performance on correct programs. (Of course, if you're really generous, you can give your customers a choice, just as is usually done for subscript bounds checking.) Kurt W. Hirchert hirchert@ncsa.uiuc.edu National Center for Supercomputing Applications
chpf127@ut-emx.UUCP (J. Eaton) (06/17/88)
In article <50500056@uxe.cso.uiuc.edu>, hirchert@uxe.cso.uiuc.edu writes: > > I'd like to make a few more observations on the issue of changing constants > in Fortran: [ stuff deleted about changing constants ] > 3. In turn, this means that it is not necessarily "wrong" to allow programs > to commit this error. It depends on whether it is more important to you > (and your customers) to detect (or protect the program from) errors or to > achieve maximum performance on correct programs. (Of course, if you're > really generous, you can give your customers a choice, just as is usually > done for subscript bounds checking.) How about just writing correct programs from the start, or if you are unsure about what variables in the argument list may be modified, don't use constants -- use a temporary variable instead and avoid this whole problem. This can also make your code easier to read. Consider the following: CALL SUB ( X, 5, 3, 2, IER ) Who can possibly tell, without looking at SUB, what 5, 3, and 2 mean? Isn't it better to write: LDX = 5 NROW = 3 NCOL = 2 CALL SUB ( X, LDX, NROW, NCOL, IER ) I think this is a lot better. Anyone else? > Kurt W. Hirchert hirchert@ncsa.uiuc.edu > National Center for Supercomputing Applications J. Eaton UT Austin Dept of Chemical Engineering Still not speaking for my employer, even if he does pay me.