From: Friedrich on 23 May 2010 16:39 I'm reading a fortran manuscript (i.e. handbook, primer) and I cannot quite understand the significance of a SAVE statement (in this case, when used in a MODULE). It states that the SAVE statement is used to ensure that variables keep their values between successive calls to the procedure. In other circumstances their values would become "undefined" as soon as the procedure returned control to the control unit. Please, could someone in (for dummies) terms explain what is it that that means ? Regards, Friedrich
From: Richard Maine on 23 May 2010 17:43 Friedrich <friedrich.schwartz@@yahoo.com> wrote: > I'm reading a fortran manuscript (i.e. handbook, primer) and I cannot > quite understand the significance of a SAVE statement (in this case, when > used in a MODULE). > > It states that the SAVE statement is used to ensure that variables keep > their values between successive calls to the procedure. In other > circumstances their values would become "undefined" as soon as the > procedure returned control to the control unit. > > Please, could someone in (for dummies) terms explain what is it that that > means ? Well, modules add a complication to the explanation, so lets do procedures first. I assume that your question relates to what "undefined" means, because I can't explain the rest of the definition you quoted in much simpler terms...at least for variables that are in procedures. If a variable is saved, then if you call a procedure multiple times, the variable doesn't do anything "funny" between calls; it has the same value when you come back to the procedure as it did when you left before. For example, consider program main call sub(.true.) call sub(.false.) call sub(.false.) stop end program main subroutine sub(initialize) logical :: initialize integer, save :: n if (initialize) n = 0 n = n + 1 write (*,*) n return end On the first call to sub, initialize is .true., so all is simple. N gets initialized to 0 and then incremented, so it prints 1. On the second call to sub, initialize is false. The value of n was SAVEd from the previous call, so it is 1 when we enter the subroutine and the n=n+1 sets it to 2, which is printed. Likewise, on the third call to sub, the value of n is 2 when we enter the procedure and the n=n+1 sets it to 3, which is printed. What would happen, though if n were not SAVE'd? The first call would act the same, printing 1. But in the second call, the value of n is not saved from the previous call. Instead, n starts out as undefined. (It actually starts out as undefined in the first call also, regardless of whether or not it is SAVE'd, there having been no previous call, but it doesn't matter because the first thing that happens in the first call is that n gets defined with the value 0). So what happens in the second call when it gets to n=n+1? N doesn't have a defined value, so how can this increment the value? To understand the answer, it is *VERY* important to keep in mind the difference between the Fortran standard and any particular compiler. The standard says that this is "illegal" (more properly, in violation of the standard) because the expression n+1 references n when n doesn't have a defined value. 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. Basically, when the standard says it violates the standard to do something such as reference an undefined variable, that is a warning that different things could happen with different compilers. Some compilers might even do what you had in mind, but other compilers might not, and the standard guarantees nothing - not even that a compiler can detect the problem. 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. In a procedure, the unsaved variables become undefined when the procedure returns. But you don't return from a module. Modules don't do anything during run-time. Procedures in a module might, but not the module itself. (Procedures in a module are just like other procedures in terms of SAVE). The USE statement for a module is more of a compile-time thing, making things from the module accessible during compilation. First, the messy full (almost) story. 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). An "active" procedure is one that has been invoked, but has not yet returned. For example, if procedure x calls procedure y, which calls procedure z, then while z is executing, all of x, y and z are active. When a module becomes inactive because there is no longer an active procedure referencing it, then the unsaved variables in the module become undefined. So in program mtest call sub1 call sub2 stop end program subroutine sub1 use m i = 42 return end subroutine sub2 use m write (*,*) i return end module m integer :: i end module m the module variable i becomes undefined when sub1 returns because there are then no active procedures that reference the module. Sub2 then has a problem because i has become undefined, so the attempt to print it is "illegal". To make this code standard conforming and do the "obvious" thing, the variable i should be given the SAVE attribute in the module. Next for the simpler version, which is all you need to know unless you are doing something really esoteric (and probably unwise). This version is enough to keep you "safe". 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. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: PcX on 23 May 2010 18:15 On May 24, 4:39 am, Friedrich <friedrich.schwartz@@yahoo.com> wrote: > I'm reading a fortran manuscript (i.e. handbook, primer) and I cannot quite > understand the significance of a SAVE statement (in this case, when used in a > MODULE). > > It states that the SAVE statement is used to ensure that variables keep their values > between successive calls to the procedure. In other circumstances their values would > become "undefined" as soon as the procedure returned control to the control unit. > > Please, could someone in (for dummies) terms explain what is it that that means ? > > Regards, > Friedrich When the variable is defined, it has the SAVE attribute. Well, I'll take an easy example. SUBROUTINE count(n) implicit none integer :: i,n INTEGER :: sum=0 !if when sum is defined, it's assigned a value. DO i=1, 10 sum=sum+i END DO n=sum END PROGRAM main implicit none INTEGER :: n CALL count(n); PRINT*, n CALL count(n); PRINT*, n END If when sum is defined, it's assigned the value "0". After the first call count(n), n will be 55, and sum is also 55. And sum has SAVE attribute, so when come into the second call count(n), sum will enter into the loop with the value "55". After the second count(n), n will be 110. That's SAVE attribute. For avoiding that result no hoping, we will write like this: SUBROUTINE count(n) implicit none integer :: i,n INTEGER :: sum sum=0 DO i=1, 10 sum=sum+i END DO n=sum END Test it. Good luck!
From: Richard Maine on 23 May 2010 18:38 PcX <xunxun1982(a)gmail.com> wrote: > When the variable is defined, it has the SAVE attribute. No. That is wrong and very misleading. My best guess is that you are referring to a variable being "initially defined." That would be true, but the omission of "initially" makes it flat wrong. No, defining a variable does not give it the SAVE atribute; if that were so, then the whole question would be moot. Also note that, even with the "initially", this is not the definition of the SAVE attribute. It is just one way that a variable can get the SAVE attribute. It is also the most confusing way, which is why I didn't go into it. I strongly recommend making the SAVE attribute explicit. Your example has more to do with what "initially defined" means than with what SAVE means. Note that your example without the SAVE attribute would work the same way if you added the SAVE attribute (with a SAVE statement). And your example with the implicit SAVE attribute would still give the wrong results even if initialization did not imply SAVE. The essential difference between those two examples is not in the SAVE attribute, but in using an assignment statement versus an initialization. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: Friedrich on 23 May 2010 19:34 On Sun, 23 May 2010 14:43:51 -0700, nospam(a)see.signature (Richard Maine) wrote: <snipping almost full reply> Mr. Maine, thank you for an I-can't-believe-somebody-would-write-an-explanation-of-this- length-just-to-help-a-newbie explanation. I won't say I understand it perfectly now (for there is a lot probably I still don't know I don't know), but this answered all my questions involving the SAVE statement, and also, a question I was about to post, about why in some libraries, variables/arrays are declared in "empty" modules, like this: > module m > integer :: i > end module m 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. ---------------------------------------- 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 - first call to save - i is declared, and assigned the value 0, and the SAVE property - 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" ?), or is this the correct behaviour, that the value of i (1) is preserved, therefore increased to 2 few lines later on ? I'm puzzled about SAVEd values and this kind of declaration&assignment of values, what behaviour should one expect ? In any case, thank you for the effort you put in. Regards, Friedrich
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: Don't understand what my program is doing Next: problem in interface |