From: Richard Maine on
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
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
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
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
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