From: Friedrich on
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
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
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
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
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