ray@rogue.llnl.gov (Ray, Scott) (08/03/90)
I have been taught that it is good programming practice to use SAVE statements in conjunction with labeled COMMON blocks to insure that the variables in COMMON get saved when exiting a program module. Apparently, the FORTRAN 77 standard makes no such guarantee unless the SAVE statement is used. Thus, when writing my own codes I religiously stick in the SAVE statement. However, I work with a lot of hand-me-down codes written by other people who take no such precautions and have never encountered any problems that could be traced to the COMMON variables being lost due to the lack of a SAVE statement. So, two questions come to mind: 1. Are there any quasi-FORTRAN 77 compliant compilers on machines in widespread use in the 1990's where COMMON variables can actually become undefined when a program module is exited and a SAVE statement has not been used? In other words, is the SAVE statement really necessary in practice (ignoring the standard)? If so, on which machines and under what conditions? 2. What could possibly be the motivation for the standard allowing variables in COMMON to be become undefined without a SAVE statement? I can't think of a case where this would be desirable behavior. Hence why isn't it built into the COMMON framework? Note that I am restricting these questions to variables in COMMON. Using a SAVE with local variables is a much more understandable issue. Scott Ray ray@icdc.llnl.gov
maine@elxsi.dfrf.nasa.gov (Richard Maine) (08/04/90)
On 3 Aug 90 09:05:43 GMT, ray@rogue.llnl.gov (Ray, Scott) said: Ray> 1. Are there any quasi-FORTRAN 77 compliant compilers on machines in Ray> widespread use in the 1990's where COMMON variables can actually Ray> become undefined when a program module is exited and a SAVE statement Ray> has not been used? In other words, is the SAVE statement really Ray> necessary in practice (ignoring the standard)? If so, on which Ray> machines and under what conditions? On CDC Cyber systems running NOS (I don't know about the newer NOS/VE systems; I haven't used them) using the segment loader (basically a form of memory overlay). Non-saved COMMON blocks could be swapped out of memory when the referencing routines returned. Program code and non-saved local variables were also swapped out. As I recall, even saved COMMON blocks and local variables could be swapped out of memory, but they were copied to disk and restored as appropriate. The non-saved ones were just discarded and became corrupted with whatever next happened to use the same memory. I recall the CDC compilers as being pretty good about standard conformance. They didn't support some of the extensions I've since become accustomed to (lower case and long variable names come to mind), but they did honest FORTRAN pretty well. Ray> 2. What could possibly be the motivation for the standard allowing Ray> variables in COMMON to be become undefined without a SAVE statement? Ray> I can't think of a case where this would be desirable behavior. Ray> Hence why isn't it built into the COMMON framework? I guess to save memory space on systems where it is tight (relative to your requirements). It certainly was tight on the Cybers of that vintage. I sure don't miss those days. Segmentation caused lots of interesting "features". Of course, it also taught me to use the SAVE statement religiously where needed. -- Richard Maine maine@elxsi.dfrf.nasa.gov [130.134.64.6]
jrbd@craycos.com (James Davies) (08/04/90)
In article <65861@lll-winken.LLNL.GOV> ray@rogue.llnl.gov writes: > >2. What could possibly be the motivation for the standard allowing > variables in COMMON to be become undefined without a SAVE statement? > I can't think of a case where this would be desirable behavior. > Hence why isn't it built into the COMMON framework? From the Fortran 77 standard, page 17-4, section 17.3: (6) The execution of a RETURN statement or and END statement within a subprogram causes all entities within the subprogram to become undefined except for the following: (...) (d) Entities in a named common block that appears in the subprogram and appears in at least one other program unit that is either directly or indirectly referencing the subprogram. Basically, this means that the standard allows the common storage to be reused for other purposes when a subprogram exits and no other currently active subprogram references it. This would allow a smart compiler and/or linker to use the same area for two named common blocks as long as they aren't both active on the same branch of the calling tree. (In practice, I don't know of any compiler that does this. It would probably break a lot of programs, especially programs that don't routinely declare every named common block in the main program.) In the presence of enough interprocedural information, a compiler could also use this provision of the standard to aid in optimization - if a common block was allowed to become undefined at subprogram exit, then variables in the common block need not be treated as output from the subprogram, and this might help dead code elimination, for example.
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (08/04/90)
In article <65861@lll-winken.LLNL.GOV>, ray@rogue.llnl.gov (Ray, Scott) writes: > 2. What could possibly be the motivation for the standard allowing > variables in COMMON to be become undefined without a SAVE statement? Overlays. Notionally, a COMMON block comes into existence when a program unit mentioning it is entered, and remains in existence as long as there is a running program unit that mentions it. After that it can go away. The specification in the standard allows an implementation to just deallocate the block then, and reallocate it with undefined contents next time it comes into existence, just like a local variable. The standard _also_ allows an implementation to keep common blocks around forever, just like local variables. > I can't think of a case where this would be desirable behavior. Remember, computers used to be _tiny_. There's a slow sorting routine called quicksort which was invented about 1960 so that sorting could be done _at all_ on a machine with about 256 words of main memory and 16k words of backing store. By the time of F77, that kind of limitation was the unlamented past, but 8Mbytes on your desktop was still the future. Using overlay techniques with data as well as code meant that you _could_ get as much memory re-use out of Fortran as you could out of Algol or Pascal. -- Distinguishing between a work written in Hebrew and one written in Aramaic when we have only a Latin version made from a Greek translation is not easy. (D.J.Harrington, discussing pseudo-Philo)
shenkin@cunixf.cc.columbia.edu (Peter S. Shenkin) (08/06/90)
In article <65861@lll-winken.LLNL.GOV> ray@rogue.llnl.gov writes: >2. What could possibly be the motivation for the standard allowing > variables in COMMON to be become undefined without a SAVE statement? This would allow storage taken up by COMMON blocks not currently in use to be used for other purposes; eg, to store automatic variables in other functions, or to store active COMMON blocks. I believe that the standard requires COMMON blocks to be saved until the entire tree of functions using them has exited; thus COMMON blocks declared in MAIN will be saved without an explicit SAVE anyway. Would someone out there more knowledgable than I please correct me if I am incorrect, or confirm this if I am correct? -P. ************************f*u*cn*rd*ths*u*cn*gt*a*gd*jb************************** Peter S. Shenkin, Department of Chemistry, Barnard College, New York, NY 10027 (212)854-1418 shenkin@cunixc.cc.columbia.edu(Internet) shenkin@cunixc(Bitnet) ***"In scenic New York... where the third world is only a subway ride away."***
hirchert@ux1.cso.uiuc.edu (Kurt Hirchert) (08/07/90)
In article <65861@lll-winken.LLNL.GOV> ray@rogue.llnl.gov writes: >2. What could possibly be the motivation for the standard allowing > variables in COMMON to be become undefined without a SAVE statement? > I can't think of a case where this would be desirable behavior. > Hence why isn't it built into the COMMON framework? a. As others have noted, the original motivation was overlays. Most people seem to see this as an obsolete feature now that address spaces have become so much larger. I agree that it is rare today to have so much code that a program will not fit in memory, but data usage has kept pace with memory sizes, do data overlaying would still be beneficial. I have heard some second-hand reports of systems that would do this, but since I haven't seen them myself, I can't swear that they actually exist. b. In a MIMD parallel processing environment, it would be possible to create separate instances of an unSAVEd COMMON block for each processor (or each task), so that multiple copies of a function or loop can be executed simultaneously operating on the "same" COMMON block. (Some vendors have created special TASK COMMONs rather than use the SAVE/noSAVE attribute to make this distinction.) Also, as someone else pointed out, if you declare your COMMON block in your main program, you don't need to SAVE them explicitly. (This indirect SAVE behavior may be why vendors created TASK COMMON rather than implementing unSAVEd COMMON this way.) -- Kurt W. Hirchert hirchert@ncsa.uiuc.edu National Center for Supercomputing Applications
gilmore@vax1.acs.udel.EDU (Scott Gilmore) (08/07/90)
In article <1990Aug6.215727.21612@ux1.cso.uiuc.edu> hirchert@ux1.cso.uiuc.edu (Kurt Hirchert) writes: >Also, as someone else pointed out, if you declare your COMMON block in your >main program, you don't need to SAVE them explicitly. >-- >Kurt W. Hirchert hirchert@ncsa.uiuc.edu >National Center for Supercomputing Applications What about BLOCK DATA subprograms? Does this implicit save behavior also apply to them? -- Scott Gilmore gilmore@vax1.udel.edu Mechanical Engineering and Center for Composite Materials, U. of Delaware
hirchert@ux1.cso.uiuc.edu (Kurt Hirchert) (08/07/90)
In article <6814@vax1.acs.udel.EDU> gilmore@vax1.udel.edu (Scott Gilmore) writes: >In article <1990Aug6.215727.21612@ux1.cso.uiuc.edu> hirchert@ux1.cso.uiuc.edu (Kurt Hirchert) writes: >>Also, as someone else pointed out, if you declare your COMMON block in your >>main program, you don't need to SAVE them explicitly. > >What about BLOCK DATA subprograms? Does this implicit save behavior also >apply to them? >-- >Scott Gilmore gilmore@vax1.udel.edu >Mechanical Engineering and Center for Composite Materials, U. of Delaware No. If a variable or array in a COMMON block is initialized (through a BLOCK DATA) and not subsequently redefined, it will remain defined even if not SAVEd, but that's all. In other words, if you are using a value in COMMON as a kind of global constant, it will work, but the mere fact that you initialize a COMMON block is not enough in general to make it retain values between CALLs. (In the overlay model, this means that an unSAVEd COMMON can still be moved out to a branch overlay with the initialization of that COMMON being done each time the overlay is loaded.) -- Kurt W. Hirchert hirchert@ncsa.uiuc.edu National Center for Supercomputing Applications
fisher@Alliant.COM (Larry Fisher) (08/11/90)
On 3 August 1990, Richard Maine) wrote: > >On CDC Cyber systems running NOS (I don't know about the newer NOS/VE >systems; I haven't used them) using the segment loader (basically a >form of memory overlay). Non-saved COMMON blocks could be swapped out >of memory when the referencing routines returned. Program code and >non-saved local variables were also swapped out. > >As I recall, even saved COMMON blocks and local variables could be >swapped out of memory, but they were copied to disk and restored >as appropriate. The non-saved ones were just discarded and became >corrupted with whatever next happened to use the same memory. > Ah, yes, the segmented loader. One of the least-used features of the CYBERS; right next to LO72 and the 8-BIT subroutines. Yeah, saved COMMON blocks were written back to disk when a segment was "swapped" out. A handy feature of the segmented loader was that the code didn't have to have SAVE statements --- named COMMON blocks could be saved via the segmented loader SAVE directive. Equally helpful is the save switch on the Fortran compiler here at Alliant. >I guess to save memory space on systems where it is tight (relative to >your requirements). It certainly was tight on the Cybers of that >vintage. I sure don't miss those days. Segmentation caused lots of >interesting "features". Of course, it also taught me to use the SAVE >statement religiously where needed. Yeah. An interesting feature [severe defiency] of the CYBER loader was that you couldn't even get a external reference cross-reference map if the program didn't fit in 400000B (131k words). I, like others, ended up writing a set of programs to cross-reference routines and common blocks. The program call-tree could be manipulated and segmented loader directives generated. Such fun :-). -- Larry Fisher Domain: fisher@alliant.com Alliant Computer Systems UUCP: {mit-eddie|linus}!alliant!fisher Littleton, MA 01460 Phone: (508) 486-1449
bam@bnlux0.bnl.gov (Bruce A. Martin) (08/17/90)
In Article 3664 of comp.lang.fortran, ray@rogue.llnl.gov (Ray, Scott) asked: >... >1. Are there any quasi-FORTRAN 77 compliant compilers on machines in > widespread use in the 1990's where COMMON variables can actually > become undefined when a program module is exited and a SAVE statement > has not been used? In other words, is the SAVE statement really > necessary in practice (ignoring the standard)? If so, on which > machines and under what conditions? > >2. What could possibly be the motivation for the standard allowing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > variables in COMMON to be become undefined without a SAVE statement? > I can't think of a case where this would be desirable behavior. > Hence why isn't it built into the COMMON framework? > >Note that I am restricting these questions to variables in COMMON. Using >a SAVE with local variables is a much more understandable issue. > > Scott Ray > ray@icdc.llnl.gov Several posters then pointed out that variables could lose their value when the COMMON block is part of an overlay. Some also noted that, back in the good old days when kilobytes were scare, you couldn't affort to keep everything around just in case somebody would need it later. Also, in Article 3695, hirchert@ux1.cso.uiuc.edu (Kurt Hirchert) stated that: >... >a. As others have noted, the original motivation was overlays. reluctant as I am to quibble with someone as lucid and (usually) precise as KWH, I must say that this misses the point somewhat: Overlays had little or nothing to do with the "motivation" for the SAVE statement! The "motivation" was simply that different processors handled memory in different ways. Some (especialy Burroughs) actually used automatic allocation, and gave up memory that wasn't needed. [ Of course, IBM "invented" virtual memory a decade later. ] [ However in those days, efficient use of resources just wasn't ] [ considered be part of a good marketing strategy in Armonk. ] [ And besides, who cares about Algol machines, anyhow? ;^) ] [ And, now back to your local station. ] It was often stated during discussions (while 77 was being developed) that what was really needed was an UNSAVE statement, so that the default was SAVE. However, the best we could do was add SAVE because the (66) default already was that unused blocks were vulnerable to loss. Upward compatiblility required them to stay so. -=o=- To understand "the motivation for the standard allowing" something, one must consider what a language standard is and why it exists. A language standard not only defines the legal forms (syntax, combinations, etc.) but it must also specify the interpretation -- if any -- for every form (and combination) that is legal. Thus, the standard is realy two documents in one: one to say what is permissible in the language (and therefore in a program), and another to say what a conforming processor must do. Unfortunately, these two purposes can get confused (often by the readers, and sometimes by the writers). Consequently, a standard cannot say that something is legal for one processor but illegal for another. Nor can it provide alternate interpretations for the same form. When processors differ in the way they handle something, and when that difference can affect program behavior, the best a standard can do is to say that the interpretation (i.e. the behavior of the program) is "processor dependent" -- EOR -- disallow it. One way to introduce processor dependence without outlawing too many programs is to say that a value may become "undefined" (which means unpredictable) under certain circumstances, but that the program is still legal if the value is never used. It is the *reference* to the undefined value that makes the program nonstandard, not its creation. (Unfortunately, this is hard to detect and creates "completeness" problems.) -=o=- In X3.9-1978, Section 1.4 ("Conformance") says that an "executable program () conforms to this standard if it uses only those forms and relationships described herein and if the executable program has an interpretation according to this standard". Section 1 notes in Appendix B also contains a useful discussion of conformance issues. By ANSI rules, the standard may not say anything about programs that are nonstandard -- not even to limit what a standard-performing processor may do to them! Therefore, saying that a program is not standard (e.g. uses an undefined value) has exactly the same effect as saying that its behavior is "processor dependent". The standard is required to be silent about the behavior of nonstandard programs! The result of this is that "undefined", "illegal", and "processor dependent" all mean the same thing: i.e. that the situation is not covered by the standard and that the standard-conforming processor is free to do as it pleases to such a program (including resetting every fourth variable to a random number and proceeding merrily along without telling you!! Or maybe like changing the owner's password!). -=o=- Returning to the main point, the "motivation" behind most of X3.9-1966 was to describe the *intersection* of the behaviors of all existing Fortran processors (plus a few cleanups and extensions), and to exclude from the language things that would cause processor-dependent behavior. Therefore, if some existing processors treated a situations in a particular way (like having more than six characters in a storage unit, or like reusing memory for unused locals and common blocks) -- or even if it merely seemed reasonable that some future processors *might* want to do things that way -- then the motivation of X3.4.3 was to write the standard so as to allow that implementation while defining the parts of the interpretation that needed to be consistent. The DO loop provides several good examples of this: Some processors keep the index in a variable while others keep it in registers and maybe store its last value or next value at the end; some fetch the final value and increment first, while others compare to memory or fetch them later; some processors have only three registers for nested loops; etc. Therefore, the committee defined a subset of the possible loop arrangements which would have the same behavior on all processors, and outlawed the rest. This is why DO parameters may not be altered within the loop and DO index values are undefined afterwards -- the standard says that all bets are off if go outside this subset, but it cannot say what exactly what will happen. The moral of the story is that standards "allow" for differing behavior that could occur on some processors by saying that a form is illegal or that the value is not dependable (and therefore is not legally usable). BAM -/s/- (bam@bnlux0.bnl.gov) Bruce A. Martin [Address given for identification only.] Grumman Space Systems [Every conceivable disclaimer applies!!] c/o National Synchrotron Light Source [Opinions are mine only, & will change,] Bldg. 725C, Brookhaven National Lab. [without notice, whenever appropriate!!] Upton, NY 11973 (516) 282-3712 [DISCLAIMER: The statements made herein do not necessarily reflect those of any other individual, group, organization, corporation, or government agency. My work on X3J3 does not in any way represent official policies or positions of my past or present employers nor those of any other sponsor or affiliate.]
bam@bnlux0.bnl.gov (Bruce A. Martin) (08/17/90)
>... >I believe that the standard requires COMMON blocks to be saved until the >entire tree of functions using them has exited; thus COMMON blocks declared >in MAIN will be saved without an explicit SAVE anyway. Would someone out there >more knowledgable than I please correct me if I am incorrect, or confirm this >if I am correct? > Correct. However, the standard requires that if SAVE is specified for a given block in one procedure, it must be so specified in ALL procedures (other than the main program) which reference it! At the last minute (San Diego, 1977 Jan.), somebody realized that a loader could have problems when the the last subroutine says that some COMMON block declared by all of the preceding ones had to be kept in SAVE space. This led to the rule that you must say SAVE in all or none of the subroutines. Logically, this should apply when the block is in main, but that was too hard to swallow. Therefore, a loader could still have a problem when the main program is the last module to be loaded! ;-) Section 8.9 is a bit confusing if you take pieces of it out of context. The *effect* of putting a block in main is the same as if you had had a SAVE statement in each subroutine that really used it. However, if you do specify SAVE in one of the subroutines -- even tho it doesn't change anything -- then you must specify it in the others. Some readers are confused by the words which say that when the block appears in the main program then "a SAVE statement in the subprogram has no efect". It has no effect, but it is still required in ALL of those subprograms if it appears in ANY of them. It is "optional" only in the main program.A I think there was an interpretation item on this in one of the FIBs. BAM -/s/- (bam@bnlux0.bnl.gov) Bruce A. Martin [Address given for identification only.] Grumman Space Systems [Every conceivable disclaimer applies!!] c/o National Synchrotron Light Source [Opinions are mine only, & will change,] Bldg. 725C, Brookhaven National Lab. [without notice, whenever appropriate!!] Upton, NY 11973 (516) 282-3712
jerry@violet.berkeley.edu (Jerry Berkman) (09/13/90)
In article <2065@bnlux0.bnl.gov> bam@bnlux0.bnl.gov (Bruce A. Martin) writes: > >The DO loop provides several good examples of this ... > ... the committee defined a subset of the possible >loop arrangements which would have the same behavior on all processors, >and outlawed the rest. This is why DO parameters may not be altered >within the loop and DO index values are undefined afterwards -- the >standard says that all bets are off if go outside this subset, but it >cannot say what exactly what will happen. > > >BAM -/s/- > (bam@bnlux0.bnl.gov) Bruce A. Martin I got a little confused about whether "standard" is referring to the 1966 or 1977 standard. In the 1977 standard (section 11.10.2): "When a DO-loop becomes inactive, the DO-variable of the DO-loop retains its last defined value." - Jerry Berkman, U.C. Berkeley, (415)642-4804 jerry@violet.berkeley.edu (normal disclaimers: opinions are my own, not my employers, etc.) opinions are my own, not my employers, etc.)