From: Richard Maine on 23 May 2010 20:15 Friedrich <friedrich.schwartz(a)yahoo.com> wrote: > On Sun, 23 May 2010 14:43:51 -0700, nospam(a)see.signature (Richard Maine) > wrote: > thank you for an I-can't-believe-somebody-would-write-an-explanation-of-this- > length-just-to-help-a-newbie explanation. You're welcome. Oddly (or not), I enjoy helping people, perhaps even particularly newbies. Those who have been around for years and keep making the same mistake over and over again, apparently never learning from the attempts at help, are a different matter. > subroutine save(j) > implicit none > integer :: i = 0, j > save i > i = i + j > write(*,*)i > end subroutine save > > program test_save > implicit none > integer :: j > j = 1 > call save(j) > call save(j) > end program test_save > ------------------ OUTPUT: ------------- > 1 > 2 > ---------------------------------------- > > Because of it, I saw no change upon removing the aforementioned from below > the subroutine declaration, and that made me going crazy, because I > thought I was doing something wrong, fundamentally. > > If I may trouble you for just one tiny detail. In the above simple > example, were we to follow the standard "to the letter", what should > exactly happen ? > To my reasoning, it should go like; > - j is declared, and assigned the value 1 Ok, sort of. But I'll quibble about one nit. Declaration is not something that "happens" during execution. I'll not repeat that quibble each time. So the only thing that "happens" here is the bit about j being assigned the value 1. > - first call to save > - i is declared, and assigned the value 0, and the SAVE property Likewise, the SAVE attribute is something that i gets at compile time. It does not "happen" when the subroutine is called. Admitedly, it is only when the subroutine is called that SAVE has observable effects, but the variable either has the attribute or does not have it, for all time. > - thanks to j, i is increased to 1, and written out > - subroutine returns "focus" to main program > - second call to save > - i is declared again, and assigned the value 0 again ... should the > problem arise here (can declared values be "declared again" ?), No, and no. i is not declared again. As noted above, declarations aren't a run-time thing at all. More importantly, no it is not assigned the value 0 again. Although the i=0 in the integer statement looks a lot like an assignment statement, it isn't one. In that context, the i=0 is an initialization. That means it hapens only on the first call to the subroutine. Actually, odds are high that it will happen before then in practice; it is usually implemented as part of the compiled code in such a way that it essentially happens when the program is loaded, but that has the same observable effects as happening during the first call to the subroutine. If you had an assignment statement i=0, that would execute for each call to the subroutine, but that integer statement is not an executable statement. It is a declaration, and the assignment-looking thing in it is an initialization. So i still has the value 1, as... > or is this the correct behaviour, that the value of i (1) is preserved, > therefore increased to 2 few lines later on ? Yes. If i were not saved, then the code would be illegal because i would be undefined (it would not have a saved value, and the initialization still would not happen on the second call either), but...a complication that I avoided in my prior post... you can't do an example quite like this in f90+ without i being saved. The initialization automatically implies that i is saved, even if you omit the SAVE statement. That's why I avoided using initialization like this in my example; I could use it to illustrate what happens with SAVE, but I could not use it to give a directly corresonding example of what happens without SAVE, because when you take the SAVE statement out, the variable still has the SAVE attribute because of the initialization. That "initialization automatically implies save" feature was new to f90, by the way. It wasn't so in f77. It was added because youy pretty much always want the SAVE attribute when you have initialization. Lots of f77 programs tended to be technically wrong because they did things like that and omitted the SAVE. People got by with it only because many f77 compilers tended to act as though everything were SAVEd anyway. WIth f90, a lot more stuff happens dynamically in ways that make compilers far more likely to actually trash values if you don't SAVE them. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: Steve Lionel on 23 May 2010 20:49 On 5/23/2010 7:34 PM, Friedrich wrote: > I guess my main confusion with the SAVE statement, in an example which I produced, > while I was trying to "figure it out" was the fact that Intel's Visual Fortran (I do not have it on > the computer I'm writing this from, so I'm unsure somewhat of the version, but it's one of the more > recent) is probably one of those compilers which save variables values, regardless of SAVE. Actually, it isn't - and this is one of a few major differences between Intel Visual Fortran and its predecessor, Compaq Visual Fortran. It can be made to do so, with an option, but "everything SAVEd" is not the default. This has been known to trip up those who wrote "invalid" programs that happened to work on some other compiler. The message I would leave for you here is not to assume that, just because you observe behavior X with a particular combination of compiler and program, that behavior X is defined by the language or by that particular implementation. -- Steve Lionel Developer Products Division Intel Corporation Nashua, NH For email address, replace "invalid" with "com" User communities for Intel Software Development Products http://software.intel.com/en-us/forums/ Intel Software Development Products Support http://software.intel.com/sites/support/ My Fortran blog http://www.intel.com/software/drfortran
From: Reinhold Bader on 24 May 2010 04:47 Hello, The Fortran 2008 draft standard indeed says that all module variables are SAVEd. Regards Reinhold Am 23.05.2010 23:43, schrieb Richard Maine: [...] > To my knowledge, there exist no compilers that don't act as though all > module variables were SAVEd anyway. There have been proposals to make > the standard go ahead and say that all module variables are SAVEd. But > unless and until the standard does say that, I'd recommend not counting > on it. There *HAVE* been compilers that made unsaved COMMON blocks lose > values, which is a simillar issue. >
From: glen herrmannsfeldt on 24 May 2010 11:54 Richard Maine <nospam(a)see.signature> wrote: (snip) > But what happens with an actual compiler? Well, pretty much anything can > happen. Some compilers might act just as though n had been saved, and > you'd never know the difference. Others might use some random value for > n - whatever happened to be left in that location of memory from some > other processing. Yes, it can very well happen that other things use the > same memory location as n when n isn't "using" it. Some other compilers > might detect that n was undefined and give you an error message; in some > sense, that is the "nicest" thing for a compiler to do, but most don't > do it. It is essentially impossible to do it for absolutely every case > of undefined variables, and it can have significant cost for some cases > where it is possible. In theory, the "anything" that can happen could be > more esoteric, but the above 3 possibilities are ones that actually > happen with some real compilers. In the days of ones complement and sign magnitude integers, a system could use negative zero as an illegal value, and detect it at run-time. Either explicitly initialized, or accidental, that could cause undefinded effects. Also, some systems might generate parity errors on fetch to a location that hasn't been previously stored into. Unlikely on any machine you find today. (snip) > Ok, now for the case of modules (and COMMON blocks, which act > essentially like modules). The part about a saved variable keeping its > value or becomming undefined is the same. So are the consequences > (anything) of referencing a variable when it is undefined. The part that > is different is in when this undefinition happens. (snip) > When an unsaved module variable becomes undefined is a little messy to > describe. Basically, an unsaved module variable stays defined as long as > any "active" procedure references the module (by having a USE statement > for the module, either directly, or indirectly by USEing some other > module, which in turn references the module in question). (snip) > If you want module variable values to "stay around", you should SAVE > them. Do this if you ever expect module variables to communicate values > between different proceures or between different calls to the same > procedure. For the most part, this probably means you should SAVE all > public module variables, which is an even simpler rule. It is probably a > pretty rare module variable that you use without wanting such > communication. It can happen, but that doesn't seem the norm. > To my knowledge, there exist no compilers that don't act as though all > module variables were SAVEd anyway. There have been proposals to make > the standard go ahead and say that all module variables are SAVEd. But > unless and until the standard does say that, I'd recommend not counting > on it. There *HAVE* been compilers that made unsaved COMMON blocks lose > values, which is a simillar issue. As far as I know, that happened with overlays. I presume one could still use overlays with Fortran 2003, but I haven't heard of anyone doing it. The overlay systems I used to use put things, including COMMON blocks, in the root segment by default, such that they would keep their value. It seems likely to me that if you did move a COMMON block (or MODULE) into an overlay that its values would not stay saved, even with the SAVE attribute. At that point, it is the programmer's responsibility to get it right, not the compiler's. -- glen
From: glen herrmannsfeldt on 24 May 2010 12:07 Steve Lionel <steve.lionel(a)intel.invalid> wrote: (snip) > Actually, it isn't - and this is one of a few major differences between > Intel Visual Fortran and its predecessor, Compaq Visual Fortran. It can > be made to do so, with an option, but "everything SAVEd" is not the > default. This has been known to trip up those who wrote "invalid" > programs that happened to work on some other compiler. > The message I would leave for you here is not to assume that, just > because you observe behavior X with a particular combination of compiler > and program, that behavior X is defined by the language or by that > particular implementation. One that happened to me a looong time ago in PL/I with CONTROLLED variables (similar to Fortran ALLOCATABLE) was accidentally FREEing and reALLOCATEing a variable, which happened to again use the same memory space. That could also happen on a stack with automatic variables. For a simple program, it might seem to work. In a more complicated program, something else will overwrite the memory location. In my PL/I program, I changed something else and the values changed. Then I had to track down why. In Fortran, the usual way to keep non-SAVEd variables from being saved is to give the routine the RECURSIZE attribute. RECURSIVE routines require a separate instance of local variables for each instance of the routine. Without the RECURSIVE attribute, it is up to the compiler to treat non-SAVEd variables as either static or automatic. In other languages, SAVE is written STATIC, as contrasted to automatic variables. (C keyword auto, pretty much never used.) -- glen
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: Don't understand what my program is doing Next: problem in interface |