For Programmers: Free Programming Magazines  


Home > Archive > Fortran > January 2006 > save attribute for module variables









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author save attribute for module variables
inidos

2006-01-22, 7:56 am

Hi,

can somebody explain me, what is the use of a SAVE attribute for a
module variable? The standard says:

"An entity with the SAVE attribute, declared in the scoping unit of a
module, retains its association status, allocation status, definition
status, and value after a RETURN or END statement is executed in a
procedure that accesses the module unless it is a pointer and its
target becomes undefined."

However, module variables should keep their properties also without
the SAVE attribute, shouldn't they? (In my expirience, they do.) Using
the following code:

-------------------------------------------
program test
use mod1

call set1(1)
call print1()
call print1()

end program test
-------------------------------------------
module mod1
implicit none
private

integer :: var
public :: set1, print1

contains

subroutine set1(val)
integer, intent(in) :: val
var =3D val
end subroutine set1

subroutine print1()
print *, "Var:", var
var =3D var + 1
end subroutine print1

end module mod1
--------------------------------------------

I obtain (with ifort at least)

Var: 1
Var: 2

So, the variable in the module scope keeps its value even without the
save attribute.

Cheers,

B=E1lint

sunnyabc

2006-01-22, 7:56 am

As far as I know, a lot of compiler regard variables declared in module
as
shared variables, like variables in common blocks. I think this is kind
of
extension of Fortran, which is supported by a lot of vendor compilers.

However, text book based on Fortran 90/95 standards (e.g., Fortran
90/95
for Scientists and Engineers by S. J. Chapman) recommends to use
"SAVE" in module if users want to ensure that the variables are shared.

Rich Townsend

2006-01-22, 9:59 pm

inidos wrote:
> Hi,
>
> can somebody explain me, what is the use of a SAVE attribute for a
> module variable? The standard says:
>
> "An entity with the SAVE attribute, declared in the scoping unit of a
> module, retains its association status, allocation status, definition
> status, and value after a RETURN or END statement is executed in a
> procedure that accesses the module unless it is a pointer and its
> target becomes undefined."
>
> However, module variables should keep their properties also without
> the SAVE attribute, shouldn't they? (In my expirience, they do.) Using
> the following code:
>
> -------------------------------------------
> program test
> use mod1
>
> call set1(1)
> call print1()
> call print1()
>
> end program test
> -------------------------------------------
> module mod1
> implicit none
> private
>
> integer :: var
> public :: set1, print1
>
> contains
>
> subroutine set1(val)
> integer, intent(in) :: val
> var = val
> end subroutine set1
>
> subroutine print1()
> print *, "Var:", var
> var = var + 1
> end subroutine print1
>
> end module mod1
> --------------------------------------------
>
> I obtain (with ifort at least)
>
> Var: 1
> Var: 2
>
> So, the variable in the module scope keeps its value even without the
> save attribute.
>
> Cheers,
>
> Bálint
>


The problem comes if your calls to setl & printl are in seperate subroutines,
*and* the routine calling these seperatue subroutines does not USE the modl
module. Then, the module goes "out of scope", and the values of module variables
will be lost *unless* they are SAVEd.

cheers,

Rich
Richard Maine

2006-01-22, 9:59 pm

inidos <aradi@phys.upb.de> wrote:

> However, module variables should keep their properties also without
> the SAVE attribute, shouldn't they? (In my expirience, they do.) Using
> the following code:

[elided]

As Rich Townsend noted, your code does not illustrate the issue. It
isn't usually returning from procedures *IN* the module that can cause
the problem. It is returning from a procedure that USEs the module.
(With procedure pointers, new to f2003, there is a way to do it by
returning from a procedure in the module, but that's a bit quirky and is
not the simple case). It is when no "active" scoping unit USEs the
module that its variables can "go away". In your example, the main
program USEs the module. The main program is always "active" in this
sense. The thread of execution is always in the main program or in
something invoked from the main program, possibly through multiple
levels of invocation. So a module that is USEd in the main program can
never illustrate the issue.

To my knowledge, there are no current compilers that actually implement
modules in a way that it matters. Nonetheless, it is still a requirement
of the standard. Code that does not use SAVE where required is
nonstandard code. That doesn't mean that it for sure won't work. It just
means that there is no guarantee that it will. With some other compiler
- possibly one that doesn't even exist yet for some new machine
architecture - the code might not work.

Therefore, I recommend using SAVE where the standard specifies, even if
it doesn't happen to make any difference for current compilers. It isn't
as though it takes a lot of work. If you are feeling "lazy" about it,
you can just put a single statement SAVE (with nothing else on it) in
the module. That says to save everything that would be meaningful to
save. That's usually pretty much the "right" answer for modules, as
normally you do want all module variables saved. My personal style is
still to specify it for each variable.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
Richard Maine

2006-01-22, 9:59 pm

sunnyabc <sis@yonsei.ac.kr> wrote:

> As far as I know, a lot of compiler regard variables declared in module
> as shared variables, like variables in common blocks. I think this is kind
> of extension of Fortran, which is supported by a lot of vendor compilers.


I find that description misleading in two ways.

1. Variables declared in modules *ARE* shared. This is not an extension.
Infact, they are more so than variables in common. For modules, it is
actually the variables that are shared. For common, in some sense it is
just the storage that is shared rather than the variables. The
distinction starts to matter when the common block layout is different
in different scoping units (a practrice that can result in horrible
messes, bugt is allowed by the standard).

But being shared has nothing to do with the issue. In particular,

2. You seem to be implying that variables in common don't have this
issue. They do. The description of how variables in common can become
undefined is almost identical to the description of the comparable thing
for modules. I'd almost say that you have the comparison backwards, in
that...

Although I know of no compilers that actually implement modules in a way
where variables can "go away", I *HAVE* used multiple compilers where
this happened for common. Not current compilers admitedly.

The fact that variables retain their values when the standard doesn't
require them to can be viewed as an extension. But it is not an
extension that the variables are shared.

> However, text book based on Fortran 90/95 standards (e.g., Fortran 90/95
> for Scientists and Engineers by S. J. Chapman) recommends to use "SAVE" in
> module if users want to ensure that the variables are shared.


I agree with that recommendation. (Though I'm not particularly fond of
that textbook in general.)

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
Michael Prager

2006-01-23, 7:04 pm

nospam@see.signature (Richard Maine) wrote:

> The
>distinction starts to matter when the common block layout is different
>in different scoping units (a practrice that can result in horrible
>messes, bugt is allowed by the standard).


After the comma, Richard has introduced a wonderful extension to
English.


--
Mike Prager, NOAA, Beaufort, NC
Address spam-trapped; remove color to reply.
* Opinions expressed are personal and not represented otherwise.
* Any use of tradenames does not constitute a NOAA endorsement.
Richard E Maine

2006-01-23, 7:04 pm

Michael Prager <Mike.Prager.indigo@noaa.gov> wrote:

> nospam@see.signature (Richard Maine) wrote:
>
>
> After the comma, Richard has introduced a wonderful extension to
> English.


That single short word serves as a sequeue to elaborate on the kind of
messses and also to contrast with the following phrase. :-)

I'll have to work a little harder to explain the "practrice". :-(

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Richard E Maine

2006-01-23, 7:04 pm

Richard E Maine <nospam@see.signature> wrote:

> That single short word serves as a sequeue


and also a segue. :-)

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
James Van Buskirk

2006-01-23, 7:04 pm

"Richard Maine" <nospam@see.signature> wrote in message
news:1h9k6od.l9egis5jttbqN%nospam@see.signature...

> To my knowledge, there are no current compilers that actually implement
> modules in a way that it matters. Nonetheless, it is still a requirement
> of the standard. Code that does not use SAVE where required is
> nonstandard code. That doesn't mean that it for sure won't work. It just
> means that there is no guarantee that it will. With some other compiler
> - possibly one that doesn't even exist yet for some new machine
> architecture - the code might not work.


Beg to differ: it can be made to matter with all compilers. The
issue arises when a module variable is of a user-defined type
with default initialization. In that event, every time the
variable comes into scope after being out of scope, the default
initialization should be applied. Since the standard doesn't
want the Fortran processor to have to keep track of when a
module goes out of scope, it evades this requirement by instead
requiring a module variable of a user-defined type with default
initialization to be given the SAVE atribute, either directly
or via an explicit initialization.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


inidos

2006-01-25, 7:57 am

Hi,

> Beg to differ: it can be made to matter with all compilers. The
> issue arises when a module variable is of a user-defined type
> with default initialization. In that event, every time the
> variable comes into scope after being out of scope, the default
> initialization should be applied. Since the standard doesn't
> want the Fortran processor to have to keep track of when a
> module goes out of scope, it evades this requirement by instead
> requiring a module variable of a user-defined type with default
> initialization to be given the SAVE atribute, either directly
> or via an explicit initialization.


Exactly this was the situation, when I began to notice the
difference, and began to wonder, what the meaning of the SAVE attribute
for module variables should be. I think to understand it now. Thank you
very much for your kind responses.

See you (maybe soon) in an other thread.

B=E1lint

Jugoslav Dujic

2006-01-26, 7:58 am

James Van Buskirk wrote:
| "Richard Maine" <nospam@see.signature> wrote in message
| news:1h9k6od.l9egis5jttbqN%nospam@see.signature...
|
|| To my knowledge, there are no current compilers that actually implement
|| modules in a way that it matters. Nonetheless, it is still a requirement
|| of the standard. Code that does not use SAVE where required is
|| nonstandard code. That doesn't mean that it for sure won't work. It just
|| means that there is no guarantee that it will. With some other compiler
|| - possibly one that doesn't even exist yet for some new machine
|| architecture - the code might not work.
|
| Beg to differ: it can be made to matter with all compilers. The
| issue arises when a module variable is of a user-defined type
| with default initialization. In that event, every time the
| variable comes into scope after being out of scope, the default
| initialization should be applied. Since the standard doesn't
| want the Fortran processor to have to keep track of when a
| module goes out of scope, it evades this requirement by instead
| requiring a module variable of a user-defined type with default
| initialization to be given the SAVE atribute, either directly
| or via an explicit initialization.

James, care to expand? Is it *illegal* to have the described
situation without the variable having SAVE attribute, or is
it required that the compiler should apply the default initialisation
on re-entering the scope? I just tried the situation you described
with CVF6.6C and presence of SAVE made no difference
(nor the compiler complained about it, even with F95 standard
checking). I can try IVF9.0 also.

--
Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.
Jan Vorbrüggen

2006-01-26, 7:58 am

> | Beg to differ: it can be made to matter with all compilers. The
> | issue arises when a module variable is of a user-defined type
> | with default initialization. In that event, every time the
> | variable comes into scope after being out of scope, the default
> | initialization should be applied. Since the standard doesn't
> | want the Fortran processor to have to keep track of when a
> | module goes out of scope, it evades this requirement by instead
> | requiring a module variable of a user-defined type with default
> | initialization to be given the SAVE atribute, either directly
> | or via an explicit initialization.
>
> James, care to expand? Is it *illegal* to have the described
> situation without the variable having SAVE attribute, or is
> it required that the compiler should apply the default initialisation
> on re-entering the scope? I just tried the situation you described
> with CVF6.6C and presence of SAVE made no difference
> (nor the compiler complained about it, even with F95 standard
> checking). I can try IVF9.0 also.


I understand James as saying the following: If the standard did not require
initialized module variables to automatically be SAVEd, you could tell, by
modifying such a variable, letting the module go out of and back into scope,
and then examining the value, tell whether your compiler implemented the
resetting of modules as they leave and enter scope, or not. As the standard
did not want this implementation difference to become visible - this is what
I believe is called a post hoc rationalization - the standard says that
initialized module variables - as indeed, if I'm not mistaken, all initialized
variables - automatically acquire the SAVE attribute. Thus, it makes no
difference to the program or the compiler whether you add the SAVE statement
or attribute in such cases or not - except, perhaps, to remind as the reader
of the code that this attribute is already implied by the initialization.

Jan
Jugoslav Dujic

2006-01-26, 7:02 pm

Jan Vorbrüggen wrote:
||| Beg to differ: it can be made to matter with all compilers. The
||| issue arises when a module variable is of a user-defined type
||| with default initialization. In that event, every time the
||| variable comes into scope after being out of scope, the default
||| initialization should be applied. Since the standard doesn't
||| want the Fortran processor to have to keep track of when a
||| module goes out of scope, it evades this requirement by instead
||| requiring a module variable of a user-defined type with default
||| initialization to be given the SAVE atribute, either directly
||| or via an explicit initialization.
||
|| James, care to expand? Is it *illegal* to have the described
|| situation without the variable having SAVE attribute, or is
|| it required that the compiler should apply the default initialisation
|| on re-entering the scope? I just tried the situation you described
|| with CVF6.6C and presence of SAVE made no difference
|| (nor the compiler complained about it, even with F95 standard
|| checking). I can try IVF9.0 also.
|
| I understand James as saying the following: If the standard did not require
| initialized module variables to automatically be SAVEd, you could tell, by
| modifying such a variable, letting the module go out of and back into scope,
| and then examining the value, tell whether your compiler implemented the
| resetting of modules as they leave and enter scope, or not. As the standard
| did not want this implementation difference to become visible - this is what
| I believe is called a post hoc rationalization - the standard says that
| initialized module variables - as indeed, if I'm not mistaken, all initialized
| variables - automatically acquire the SAVE attribute. Thus, it makes no
| difference to the program or the compiler whether you add the SAVE statement
| or attribute in such cases or not - except, perhaps, to remind as the reader
| of the code that this attribute is already implied by the initialization.

I find your reasoning logical and an "obvious thing to do", but that's not
how I parse:

"instead requiring a module variable of a user-defined type with default
initialization to be given the SAVE atribute, either directly via an explicit
initialization."

I interpret the last part of the sentence as "it is programmer's duty to attach
the SAVE attribute (one way or another)" rather than "the save-semantics is
imposed automatically by the compiler". But let's wait for James.

--
Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Ron Shepard

2006-01-26, 7:02 pm

In article <43s2kkF1na8s8U1@individual.net>,
Jan Vorbrüggen <jvorbrueggen-not@mediasec.de> wrote:

>
> I understand James as saying the following: If the standard did not require
> initialized module variables to automatically be SAVEd, you could tell, by
> modifying such a variable, letting the module go out of and back into scope,
> and then examining the value, tell whether your compiler implemented the
> resetting of modules as they leave and enter scope, or not.


I don't think this statement is correct. The standard does not
require "reinitialization" of objects when they go out of scope.
This might be a way to detect how a particular compiler works, but
it is not a test of the standard.

Also note that the discussion above is about an initialized
component of a user-define type. In this case the standard requires
that the variable of user-defined type must be saved (which then
includes all components, not just the ones that are initialized).
It is not about a simple variable in a module.

In practice, some compilers give warnings in this case, and others
don't. This surprised me a little when I had working code running
on several compilers, and when I ported it to a new compiler I
suddenly got dozens of compile-time messages. I felt confident that
it was a compiler bug until I read the details of this, and then I
realized that my code had really been incorrect all along. It might
have been possible to get error messages with the other compilers
with the appropriate syntax checking turned on, it just never
occurred to me that there was a problem.

$.02 -Ron Shepard
Jan Vorbrüggen

2006-01-26, 7:02 pm

Jugoslav:

> I find your reasoning logical and an "obvious thing to do", but that's not
> how I parse:
>
> "instead requiring a module variable of a user-defined type with default
> initialization to be given the SAVE atribute, either directly via an explicit
> initialization."


That quote is missing a vital "or" between "directly" and "via".

> I interpret the last part of the sentence as "it is programmer's duty to attach
> the SAVE attribute (one way or another)" rather than "the save-semantics is
> imposed automatically by the compiler". But let's wait for James.


The subject of the sentence in question is "the standard", which also is the
subject of "requiring" above. The point is that _either_ the programmer gives
it the SAVE attribute explicitly _or_ the initialization does that directly,
as the standard dictates that such an initialization carries this attribute
with it implicitly. Don't let yourself be fazed by James writing "explicit
initialization" here 8-)...

Jan
Jan Vorbrüggen

2006-01-26, 7:02 pm

> I don't think this statement is correct. The standard does not
> require "reinitialization" of objects when they go out of scope.


But that's the whole point, man! The standard does not require this
because that would be the only possible semantics if it didn't evade
the problem, as James so nicely put it, by automatically attaching
the SAVE attribute to all initialized variables.

> Also note that the discussion above is about an initialized
> component of a user-define type. In this case the standard requires
> that the variable of user-defined type must be saved (which then
> includes all components, not just the ones that are initialized).
> It is not about a simple variable in a module.


I believe this is incorrect. A simple variable that is initialized
falls under the same rule. The same holds true for scope-local variables
that are initialized, for much the same reason - although James's
"evade" argument doesn't apply in this case.

> In practice, some compilers give warnings in this case, and others
> don't. This surprised me a little when I had working code running
> on several compilers, and when I ported it to a new compiler I
> suddenly got dozens of compile-time messages. I felt confident that
> it was a compiler bug until I read the details of this, and then I
> realized that my code had really been incorrect all along.


This definitely isn't an error, and IMNSHO doesn't merit a warning.
An informational message would be OK, as this is the way, IMO, to
point out usage that might be unintended.

Jan
Richard E Maine

2006-01-26, 7:03 pm

Jan Vorbrüggen <jvorbrueggen-not@mediasec.de> wrote:


> I understand James as saying the following: If the standard did not require
> initialized module variables to automatically be SAVEd,...


While I'm not James, I can tell that you are confusing two completely
different things. James was talking about "default initialization". That
is *NOT*, repeat *NOT* the same thing as initialization. The differences
are important.

Default initialization is in a type definition and applies to all
objects of the type. If something is default-initialized, that does
*NOT* mean it is initialized. Yes, the terminology is easy to
misunderstand on that point.

So all discussion about the implications of being initialized is a
different subject, and gives wrong conclusions. When something is
default-initialized, it is *NOT* implicitly saved (well, not because of
that, anyway).

The condition in the standard on default initialization requires the
user to make a module variable saved if it has default initialization.
From 1.1 of the standard. "Except where stated otherwise, such
requirements and prohibitions apply to programs rather than processors."
This one isn't stated otherwise, so it is a requirement on the program.
Namely, you have to specify the SAVE or the program is nonconforming.
(adding "real" initialization would be one way to make the variable
SAVED, but that would override the default initialization anyway).

Since code with an unsaved, default-initialized module variable is
nonstandard, a compiler is allowed to XXXXX about it. Hmm. I don't
recall whether it was a constraint or not and don't want to run over and
check, so I'm not sure it is required that the compiler be able to
XXXXX. But in any case, it is certainly allowed for the compiler to
XXXXX and then continue on anyway, or to XXXXX only if a "be-real-picky"
flag is set.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
James Van Buskirk

2006-01-26, 7:03 pm

"Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
news:43rsemF1osjnvU1@individual.net...

> James, care to expand? Is it *illegal* to have the described
> situation without the variable having SAVE attribute, or is
> it required that the compiler should apply the default initialisation
> on re-entering the scope? I just tried the situation you described
> with CVF6.6C and presence of SAVE made no difference
> (nor the compiler complained about it, even with F95 standard
> checking). I can try IVF9.0 also.


Richard has done an excellent job of explaining the situation
here. In ISO/IEC 1539-1:1997(E), fourth constraint in section
11.3:

"Constraint: If an object of a type for which component-
initialization is specified (R429) appears in the
specification-part of a module and does not have
the ALLOCATABLE or POINTER attribute, the object
shall have the SAVE attribute."

Here's an example:

module bad
implicit none
type default_initialization
integer :: x = 42
end type default_initialization
type(default_initialization) t
end module bad

program test
use bad
implicit none

write(*,*) t
end program test

lf95 Express v. 7.10.02 compiling with -f95 says:

Compiling file module_init_1.f90.
Compiling program unit bad at line 1:
2070-S: "module_init_1.f90", line 6: 't' shall have the SAVE attribute;
has ty
pe for which component initialization was specified in a MODULE.
Compiling program unit test at line 8:
1370-S: "module_init_1.f90", line 10: Module 'bad' is not available.
2018-S: "module_init_1.f90", line 13: When IMPLICIT NONE is specified, 't'
mus
t be declared in a type declaration statement.
Encountered 3 errors, 0 warnings in file module_init_1.f90.

ifort W_FC_C_9.0.028 compiled with /c /stand:f95 has no
adverse comments on compilation and links to a result that
prints

42

g95 gcc version 4.0.2 (g95!) Dec 21 2005 compiled with
g95 -std=f95 module_init_1.f90 -omodule_init_1 says:

In file module_init_1.f90:6

type(default_initialization) t
1
Error: Module variable 't' at (1) with a default initialization must have
the SA
VE attribute

Good for Andy!

Alternatively:

module good
implicit none
type default_initialization
integer :: x = 42
end type default_initialization
type(default_initialization), save :: t
end module good

program test
use good
implicit none

write(*,*) t
end program test

Now all the above compilers like the code, but CVF 6.6C3
compiled with /stand:f95 in force says:

module_init_2
module_init_2.F90(6) : Warning: The SAVE attribute may only be declared for
obje
cts in a subprogram [SAVE]
type(default_initialization), save :: t
---------------------------------^

Too bad it's too late to fix this. At least the ifort behavior
is reparable.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


James Van Buskirk

2006-01-26, 7:03 pm

"Jan Vorbrüggen" <jvorbrueggen-not@mediasec.de> wrote in message
news:43sapgF1ph6u4U1@individual.net...

> Jugoslav:


attach[color=darkred]
is[color=darkred]
[color=darkred]
> The subject of the sentence in question is "the standard", which also is

the
> subject of "requiring" above. The point is that _either_ the programmer

gives
> it the SAVE attribute explicitly _or_ the initialization does that

directly,
> as the standard dictates that such an initialization carries this

attribute
> with it implicitly. Don't let yourself be fazed by James writing "explicit
> initialization" here 8-)...


Jugoslav's got it right here, and I am kind of worried about what
you think should happen in this situation. I would feel more
comfortable if you stated your understanding of the topic after
reading Richard's excellent post to this thread today, because
at this point in the thread you've got it so wrong and I would like
to be reassured that you have it right after reviewing this thread.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Richard E Maine

2006-01-26, 7:03 pm

James Van Buskirk <not_valid@comcast.net> wrote:

> "Constraint: If an object of a type for which component-
> initialization is specified (R429) appears in the
> specification-part of a module and does not have
> the ALLOCATABLE or POINTER attribute, the object
> shall have the SAVE attribute."


And while the reason for pointers being an exception is "obvious" enough
(the pointer isn't the "real" object and thus doesn't have the issue;
default initialization of the pointer's target isn't affected by the
fact that the pointer "goes away"), I keep forgetting why allocatables
are ok. Hmm.... I know I've looked this up or asked about it before...
probably multiple times... but I still forget the answer...

I guess it is probably related to [115:9-11], the para after Note 6.23,
which says that it is processor-dependent whether or not an unsaved
allocatable module variable gets deallocated or not. Although it is
processor-dependent which happens, you can use the allocated intrinsic
to tell whether it happened or not. So I suppose that is different from
the case of a nonallocatable, where there is no standard-conforming way
to even tell. Anyway, I think that's probably the reason.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
James Van Buskirk

2006-01-26, 7:03 pm

"Ron Shepard" <ron-shepard@NOSPAM.comcast.net> wrote in message
news:ron-shepard-F3BECA.10102726012006@comcast.dca.giganews.com...

> I don't think this statement is correct. The standard does not
> require "reinitialization" of objects when they go out of scope.
> This might be a way to detect how a particular compiler works, but
> it is not a test of the standard.


While I may not have been sufficiently clear about this point,
what I was thinking about was ISO/IEC 1539-1:1997(E), section
14.7.5:

"Variables become defined as follows:
....
(19) Invocation of a procedure that contains a nonsaved local
object that is not a dummy argument, is not accessed by
use or host association, has neither the ALLOCATABLE
not POINTER attribute, and is of a derived type in which
default initialization is specified for any direct
components, causes those components of the object to
become defined."

This is the reason, in my opinion, for the constraint about
module variables of a user-defined type with default
initialization to have the SAVE attribute: for the standard
to be consistent with the above about module variables, the
Fortran processor would have to detect exactly when the
module variables went out of scope so that they could be
given their default initializations at the appropriate times.
It's much easier to implement and intuitive for the user if
all module variables effectively stay in scope indefinitely.
However, an implementor might also want to clear out of
scope module variables from memory at will. It should be
clear to the reader that the constraint is there to make
life easier for implementors.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Jan Vorbrüggen

2006-01-27, 3:59 am

> While I'm not James, I can tell that you are confusing two completely
> different things. James was talking about "default initialization". That
> is *NOT*, repeat *NOT* the same thing as initialization. The differences
> are important.


Ah - I can't remember whether the initial post made it clear default
initialization was the topic or not, and I can't check, but I do agree
I didn't note the distinction and thus went off into a different direction.
Now I understand why James wrote "explicit initialization" in one place.

> Default initialization is in a type definition and applies to all
> objects of the type. If something is default-initialized, that does
> *NOT* mean it is initialized. Yes, the terminology is easy to
> misunderstand on that point.


Well, of course the type _definition_ as such can't intialize anthing,
as no object to initialize exists at that point. However, when that
type definition is used to declare an object, _that_ object is initialized.
And why should these two types of initialization be different in the eyes
of the standard? I consider this a bug. It means that these two definitions
that are identical to all intents and purposes (copy&paste to some degree
from James's post):

module definit
implicit none
type test1
integer :: x = 42
end type test1
type(test1):: t1

type test2
integer :: x
end type test2
type(test2) :: t2 = test2(42)
end module definit

are actually different: The second acquires the SAVE attribute by magic...
err...fiat of the standard, while in the first case the programmer needs
to supply it to turn it into a standard-conforming program. Why can't the
same rule apply to the first case as well? The processor certainly knows
that the attribute is needed: otherwise it couldn't enforce the constraint
(it does need to be able to enforce constraints, does it not?) James cited
from F95 section 11.3. And the programmer must know the object has default
initialization, IMO, because otherwise he wouldn't be able to use the object
properly anyway. And indeed the standard, as it currently stands, demands
that knowledge of him in order to produce a standard-conforming program.
So why leave her the choice where she has none?

I needed to think about the case James mentioned in a different follow-up
(from F95 section 14.7.5), but here the situation is different: the pro-
grammer is actually given a choice whether he wants such a local object to
have SAVE or non-SAVE semantics, and they do make a difference; in this
case the standard bows to the implementors again (understandably so) by
making all local variables having initialization SAVE by fiat, thus brea-
king the conceptual symmetry (IMO) of default and explicit initialization.
But, as we have discussed before, the alternative is available to the
programmer by making the initialization through an executable statement
instead, while in the case of the module variables - as they are meant
to be shared - there is no canonic way of making the distinction.

Jan
Richard E Maine

2006-01-27, 7:01 pm

Jan Vorbrüggen <jvorbrueggen-not@mediasec.de> wrote:

> And why should these two types of initialization be different in the eyes
> of the standard? I consider this a bug.


Whatever. I'm not prepared to get off onto that long discusssion at the
moment. I'll just note the most important part - that the difference
does exist, plus the secondary one - that it was intentional.

Whether or not it was wise is debatable. I might personally have argued
against the whole concept of implicit save (without which there would be
no difference here), but I do understand some of the counter-arguments
in favor of it.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Ron Shepard

2006-01-27, 7:01 pm

In article <1h9te0j.1jgrrto936wf0N%nospam@see.signature>,
nospam@see.signature (Richard E Maine) wrote:

> I might personally have argued
> against the whole concept of implicit save (without which there would be
> no difference here), but I do understand some of the counter-arguments
> in favor of it.


This implicit save (even of simple variables) is something that I
avoid using too. Whether it is with an initialization expression or
a data statement (as in f77), I have always thought that if the
variable was expected to be saved, then it should have an explicit
save attribute. This makes the intention of the programmer clear,
and it avoids tracking down bugs related to those variables being
changed, and a casual glance of the code by someone not familiar
with these details of the language might think that these local
variables were either constant, or reinitialized on each entry.

Even in f77, I would have preferred for this to be a requirement
placed on the programmer (hopefully with compiler error message
support). This way, if the programmer wants reinitialization of
that variable on each entry, he would know, without a doubt, that it
must be done with an executable statement rather than with a data
statement or with an initialization expression.

$.02 -Ron Shepard
Richard E Maine

2006-01-27, 7:01 pm

Ron Shepard <ron-shepard@NOSPAM.comcast.net> wrote:

> Even in f77, I would have preferred for this to be a requirement
> placed on the programmer


It *WAS* a requirement of f77. The implicit save feature was new to f90.
And though I'm not personally fond of the feature, it did respond to
what I might call existing common practice - that is many (even most)
users ignored the requirement (or were unaware of it), but...

> (hopefully with compiler error message support).


That part wasn't a requirement in f77. In fact, f77 had *NO*
requirements for compiler error messages. Requiring compiler diagnostic
caapability at all was new to the f90 standard. Of course, f77 and
earlier compilers invariably had diagnostic capability for some things
(I know of no exceptions), but this was not a requirement of the
standard.

F90 doesn't have requirements on this kind of thing though, because it
is not, in general compile-time detectable. Specific cases are, but the
general case is not. While requirement for run-time error detection has
often been discussed, that has long been a controversial subject, and
curently the standard avoids that rather strongly (without using the
actual words "run time" or "compile time".)

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
James Van Buskirk

2006-01-27, 9:57 pm

"Jan Vorbrüggen" <jvorbrueggen-not@mediasec.de> wrote in message
news:43u8cqF1pic92U1@individual.net...

> Well, of course the type _definition_ as such can't intialize anthing,
> as no object to initialize exists at that point. However, when that
> type definition is used to declare an object, _that_ object is

initialized.
> And why should these two types of initialization be different in the eyes
> of the standard? I consider this a bug. It means that these two

definitions
> that are identical to all intents and purposes (copy&paste to some degree
> from James's post):


> module definit
> implicit none
> type test1
> integer :: x = 42
> end type test1
> type(test1):: t1


> type test2
> integer :: x
> end type test2
> type(test2) :: t2 = test2(42)
> end module definit


> are actually different: The second acquires the SAVE attribute by magic...
> err...fiat of the standard, while in the first case the programmer needs
> to supply it to turn it into a standard-conforming program. Why can't the
> same rule apply to the first case as well? The processor certainly knows
> that the attribute is needed: otherwise it couldn't enforce the constraint
> (it does need to be able to enforce constraints, does it not?) James cited
> from F95 section 11.3. And the programmer must know the object has default
> initialization, IMO, because otherwise he wouldn't be able to use the

object
> properly anyway. And indeed the standard, as it currently stands, demands
> that knowledge of him in order to produce a standard-conforming program.
> So why leave her the choice where she has none?


> I needed to think about the case James mentioned in a different follow-up
> (from F95 section 14.7.5), but here the situation is different: the pro-
> grammer is actually given a choice whether he wants such a local object to
> have SAVE or non-SAVE semantics, and they do make a difference; in this
> case the standard bows to the implementors again (understandably so) by
> making all local variables having initialization SAVE by fiat, thus brea-
> king the conceptual symmetry (IMO) of default and explicit initialization.
> But, as we have discussed before, the alternative is available to the
> programmer by making the initialization through an executable statement
> instead, while in the case of the module variables - as they are meant
> to be shared - there is no canonic way of making the distinction.


I think you get it at this point, but you don't seem to have the
same sort of warm and fuzzy feeling about the language's choices
about unsaved variables as I do. Let me present some examples:

module funcs
implicit none
type t1
integer :: x = 42
end type t1
contains
recursive subroutine recursive_example(depth)
integer, intent(in) :: depth
integer :: saved = 0
integer :: automatic

saved = depth
automatic = depth
write(*,'(3(a,i0))') repeat(' ',depth)//'At depth = ', &
depth,', saved = ',saved,', automatic = ',automatic
if(depth < 10) call recursive_example(depth+1)
write(*,'(3(a,i0))') repeat(' ',depth)//'At depth = ', &
depth,', saved = ',saved,', automatic = ',automatic
end subroutine recursive_example

subroutine save_or_not
type(t1) default
type(t1) :: explicit = t1(42)

write(*,'(2(a,i0))') 'On entry: default = ', &
default,', explicit = ',explicit
default%x = default%x+1
explicit%x = explicit%x+1
write(*,'(2(a,i0))') 'After update: default = ', &
default,', explicit = ',explicit
end subroutine save_or_not

subroutine allocatable_test
integer, allocatable :: automatic(:)
integer, allocatable, save :: saved(:)

if(allocated(automatic)) then
write(*,'(a,i0)') 'On entry, shape(automatic) = ', &
shape(automatic)
deallocate(automatic)
else
write(*,'(a)') 'On entry, automatic is not allocated'
end if
if(allocated(saved)) then
write(*,'(a,i0)') 'On entry, shape(saved) = ', &
shape(saved)
deallocate(saved)
else
write(*,'(a)') 'On entry, saved is not allocated'
end if
allocate(automatic(5),saved(7))
if(allocated(automatic)) then
write(*,'(a,i0)') 'On exit, shape(automatic) = ', &
shape(automatic)
else
write(*,'(a)') 'On exit, automatic is not allocated'
end if
if(allocated(saved)) then
write(*,'(a,i0)') 'On exit, shape(saved) = ', &
shape(saved)
else
write(*,'(a)') 'On exit, saved is not allocated'
end if
end subroutine allocatable_test
end module funcs

program test
use funcs
implicit none

write(*,'(a)') 'Invoking recursive_example'
call recursive_example(1)
write(*,'(/a)') 'Invoking save_or_not a couple of times'
call save_or_not
call save_or_not
write(*,'(/a)') 'Invoking allocatable_test a couple of times'
call allocatable_test
call allocatable_test
end program test

The first subroutine, recursive_example, is there just to
illustrate the fact that there is really a difference
between saved and automatic variables, and that the
programmer has the ability to control which is which.
It was in writing recursive procedures that I became
acutely aware of this aspect of the language; f77 code
doesn't have this sort of distinction.

The second subroutine, save_or_not, makes the distinction
between explicit initialization and default initialization.
Default initialization behaves much the same way as my
limited understanding of C language initializations: on
every entry to the procedure, the default value is loaded
into the local variable. Explicit initialization has two
effects: the initial value is loaded into the local
variable on program startup, and the local variable is
assigned a permanent (for the life of the program) memory
address, common to all instances of the procedure. Thus
the user can choose between two paradigms, the C paradigm
and the f77 paradigm, where a user-defined type is concerned.

The third example, subroutine allocatable_test, is another
instance where the behavior for a saved and an unsaved
variable are both well-defined but different. I include
this because I have actually been burned by forgetting to
carefully consider this particular difference in the past.

On compilation with lf95 express v. 7.10.02,
lf95 -f95 -nconcc save_or_not

we get:

C:\LF9556\James\clf\save_or_not>save_or_not
Invoking recursive_example
At depth = 1, saved = 1, automatic = 1
At depth = 2, saved = 2, automatic = 2
At depth = 3, saved = 3, automatic = 3
At depth = 4, saved = 4, automatic = 4
At depth = 5, saved = 5, automatic = 5
At depth = 6, saved = 6, automatic = 6
At depth = 7, saved = 7, automatic = 7
At depth = 8, saved = 8, automatic = 8
At depth = 9, saved = 9, automatic = 9
At depth = 10, saved = 10, automatic = 10
At depth = 10, saved = 10, automatic = 10
At depth = 9, saved = 10, automatic = 9
At depth = 8, saved = 10, automatic = 8
At depth = 7, saved = 10, automatic = 7
At depth = 6, saved = 10, automatic = 6
At depth = 5, saved = 10, automatic = 5
At depth = 4, saved = 10, automatic = 4
At depth = 3, saved = 10, automatic = 3
At depth = 2, saved = 10, automatic = 2
At depth = 1, saved = 10, automatic = 1

Invoking save_or_not a couple of times
On entry: default = 42, explicit = 42
After update: default = 43, explicit = 43
On entry: default = 42, explicit = 43
After update: default = 43, explicit = 44

Invoking allocatable_test a couple of times
On entry, automatic is not allocated
On entry, saved is not allocated
On exit, shape(automatic) = 5
On exit, shape(saved) = 7
On entry, shape(automatic) = 5
On entry, shape(saved) = 7
On exit, shape(automatic) = 5
On exit, shape(saved) = 7

I already owe ifort a bug report for this thread for not
catching the constraint from section 11.3, and we see
that I now also owe lf95 a report for failing on section
6.3.1.2 on the above example.

I hope the above examples make more clear why the decisions
of the committee regarding the behavior of variables without
the SAVE attribute are IMO rational.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Ron Shepard

2006-01-28, 3:57 am

In article <1h9ti0j.gblhqr18rubwkN%nospam@see.signature>,
nospam@see.signature (Richard E Maine) wrote:

>
> It *WAS* a requirement of f77. The implicit save feature was new to f90.


My mistake, I thought it was the other way. I have probably added
SAVE statements for thousands of variables over the years in f77
code that I inherited from other programmers.

$.02 -Ron Shepard
Sjouke Burry

2006-01-28, 3:57 am

Ron Shepard wrote:
> In article <1h9ti0j.gblhqr18rubwkN%nospam@see.signature>,
> nospam@see.signature (Richard E Maine) wrote:
>
>
>
>
> My mistake, I thought it was the other way. I have probably added
> SAVE statements for thousands of variables over the years in f77
> code that I inherited from other programmers.
>
> $.02 -Ron Shepard

MS fortran F77 (3.31 /5.1) DEC F66? ,Acorn F77.
all the ones I ever used,save was default.
Used recursion with MS 5.1, had to add "auto",
and a dummy call routine, because direct
recursion was forbidden.
So auto variables as far as I know are at least
on three platforms not the default ones.
Richard Maine

2006-01-28, 3:57 am

Sjouke Burry <burrynulnulfour@ppllaanneett.nnlll> wrote:

> Ron Shepard wrote:

It might greatly shock you to know, Ron, that just because it was
required by the standard, that doesn't mean all programmers did it. :-)
One of the arguments advanced for adding the initialization-implies-save
to f90 was that it made significant numbers of existing
non-standard-conforming f77 codes into standard-conforming f90 ones.
[color=darkred]
> MS fortran F77 (3.31 /5.1) DEC F66? ,Acorn F77.
> all the ones I ever used,save was default...


The question was about what the standard required programmers to do. The
fact that nonstandard code sometimes works on some compilers is a
different matter. Code that assumed that save was the default was
nonstandard code, which worked on some (or even most) f77 compilers.

> So auto variables as far as I know are at least
> on three platforms not the default ones.


Note that "automatic" is not the opposite of saved in the standard. The
opposite of saved is in this case, undefined - meaning that anything can
happen. Any code that even "looked" to see what had happened was making
an illegal reference to the variable according to the standard.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
Jan Vorbrüggen

2006-01-30, 3:57 am

James, thanks for the examples. That behaviour is as one would expect
(except for the bug you note).

> I hope the above examples make more clear why the decisions
> of the committee regarding the behavior of variables without
> the SAVE attribute are IMO rational.


Oh, there's no question that there is value to non-SAVEd variables
- indeed, that they are needed in order to do certain things.

The main question of my previous post, however, was why the property
of SAVE-by-fiat applied only to one case, where it would make more
sense to also apply it to other cases - in particular as the standard
requires SAVE at that point, making programs not containing SAVE non-
compliant. Thus there is no choice, but the programmer has to make it
explicit in the code in the second case and not in the first. Why?
I can see neither technical nor philosophical (if you will) reason for
the different behaviour.

BTW, what does the standard say about module variables with explicit
initializsation - must they be SAVEd, and if so are they by-fiat or not?

Jan
Richard E Maine

2006-01-30, 7:02 pm

Jan Vorbrüggen <jvorbrueggen-not@mediasec.de> wrote:

> BTW, what does the standard say about module variables with explicit
> initializsation - must they be SAVEd, and if so are they by-fiat or not?


In asking that question, I think you illustrate the answer to your
question of why there is a difference between the case of explicit
initialization and that default initialization.

You seem to be considering module variables as a special case. Mostly,
they aren't. The standard says essentially nothing about how explicit
initialization implies save for module variables. It works the same way
with module variables as with any others. Do you know the answer for
non-module variables? Then it is the same answer. (Yes, explicit
initialization implies save). Likewise, the standard says nothing about
how default initialization implies save for module variables. The answer
is the same as for nonmodule ones. (No, default initialization does not
imply save).

In order to make default initialization imply save for module variables,
it would have to be special-cased. That's because you "can't" make
default initialization imply save in general. Default initialization is
too general for that. It applies to things like dummy arguments, where
save makes no sense (without major redefinitions of what dummy arguments
mean). It applies to other things where save makes sense, but you would
not want it to be forced, such as local variables of a recursive
procedure. Basically, if default initialization implied save, you would
have just made it impossible to have a nonsaved variable of the type.
That just doesn't "work".

One could possibly special-case the behavior for module variables, but
the standard doesn't. Instead of special-casing the behavior, the
standard prohibits the situation where the "normal" behavior causes
"issues".

If you wanted to make explicit and default initializaation act the same
in terms of implying save, I think the only way to do it would be to
make them both *NOT* imply save (which might have been my preference,
but we already alluded to that discussion). Trying to make default
initialization imply save is just going in the wrong direction in my
opinion. You'd have to start adding lots of special cases and exceptions
for the sake of getting rid of one.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Brooks Moses

2006-01-31, 4:08 am

Jugoslav Dujic wrote:
> I find your reasoning logical and an "obvious thing to do", but that's not
> how I parse:
>
> "instead requiring a module variable of a user-defined type with default
> initialization to be given the SAVE atribute, either directly via an explicit
> initialization."
>
> I interpret the last part of the sentence as "it is programmer's duty to attach
> the SAVE attribute (one way or another)" rather than "the save-semantics is
> imposed automatically by the compiler". But let's wait for James.


Your interpretation is correct: It is the programmer's duty. But you're
missing the followup point, which wasn't directly stated in that quote.

If the programmer fails in this duty by omitting the SAVE, then the
result becomes undefined behavior, and the compiler can do what it
wants, which generally tends to be "pretend that the programmer had
included the SAVE" because that's by far the easiest thing to do.

If the SAVE were not required, then the behavior with an omitted SAVE
would not be undefined -- and, in particular, it would be defined as
something that would be annoying to include in the compiler.

Does that clarify the interpretion any?

- Brooks


--
The "bmoses-nospam" address is valid; no unmunging needed.
Brooks Moses

2006-01-31, 4:08 am

Jan Vorbrüggen wrote:
> module definit
> implicit none
> type test1
> integer :: x = 42
> end type test1
> type(test1):: t1
>
> type test2
> integer :: x
> end type test2
> type(test2) :: t2 = test2(42)
> end module definit
>
> are actually different: The second acquires the SAVE attribute by magic...
> err...fiat of the standard, while in the first case the programmer needs
> to supply it to turn it into a standard-conforming program. Why can't the
> same rule apply to the first case as well?


My off-the-cuff argument would be:

module definit2
use definit
type(test1) :: x

contains
subroutine set(y)
integer :: y
x = y
end subroutine
integer function get()
get = x
end function
end module definit2

Presume that this is from some existing code that I'm reading, which I
can presume is standard-conforming. (Ha!) Further presume that I don't
have module definit in front of me at the moment. When I'm writing code
that uses this module, can I rely on x having the SAVE attribute, or not?

With your proposal, the answer is "I don't know." In actuality,
assuming this is standard-conforming, the question wouldn't have arisen
because that would have to be "type(test1), save :: x".

(I don't know whether I think this argument is very solid or not, so
don't take it as a defense of any opinion I might have; I'm merely
putting it forth for consideration.)

- Brooks


--
The "bmoses-nospam" address is valid; no unmunging needed.
Jugoslav Dujic

2006-01-31, 4:08 am

Brooks Moses wrote:
| Jugoslav Dujic wrote:
|| I find your reasoning logical and an "obvious thing to do", but that's not
|| how I parse:
||
|| "instead requiring a module variable of a user-defined type with default
|| initialization to be given the SAVE atribute, either directly via an explicit
|| initialization."
||
|| I interpret the last part of the sentence as "it is programmer's duty to
|| attach the SAVE attribute (one way or another)" rather than "the
|| save-semantics is imposed automatically by the compiler". But let's wait for
|| James.
|
| Your interpretation is correct: It is the programmer's duty. But you're
| missing the followup point, which wasn't directly stated in that quote.
|
| If the programmer fails in this duty by omitting the SAVE, then the
| result becomes undefined behavior, and the compiler can do what it
| wants, which generally tends to be "pretend that the programmer had
| included the SAVE" because that's by far the easiest thing to do.
|
| If the SAVE were not required, then the behavior with an omitted SAVE
| would not be undefined -- and, in particular, it would be defined as
| something that would be annoying to include in the compiler.
|
| Does that clarify the interpretion any?

Yes, the interpretation was clarified by Richard and James long time
ago, and their further discussion with Jan went aside, so I wasn't
inclined to reply. However, it's indeed good to have a short definitive
reply like yours. Thanks.

--
Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

Jan Vorbrüggen

2006-01-31, 7:02 pm

Let me try to summarize.

We have three different kinds of initialization:

- default
- explicit
- run-time (i.e., by executable statements)

The first two are syntactic sugar, as they can both be (and, in some cases,
under the hood must be) implemented by using the third. In a broad sense,
they are "equivalent" - except for implementation details, where all this
confusion comes from, IMO.

SAVE is really orthogonal to that. It is in its attempt to pamper implemen-
tors that the standard connects these two independent issues.

Now, explicit initialization is possible in a smaller number of cases than
than default initialization - for instance, it's not possible for dummy
arguments.

In order to make life easier for existing implementations that use compile-
time (instead of run-time) initialization, the standard mandates that ex-
plicit initialization implies SAVE. (Yes, I know the words aren't in there,
but we all know that's at least part of the rationale.) Technically, this
is unnecessary, since a standard-compliant processor needs to implement
under-the-hood-run-time-initialization in any case (e.g., for INTENT(OUT)
default initialized dummy arguments) and could do so for non-SAVED expli-
citly initialized variables also.

Philosophically, this avoids a commitment, by the standard, on whether the
programmer can place any reliance on the semantics of non-SAVEd variables:
because the one case where you could tell the difference between implemen-
tations is disallowed by fiat, no commitment needs to be made. (It occurs
to me that, alternatively, the standard could modify the rules of when an
object or subobject becomes (un)defined, but I suppose that would imply
many changes all over the place that no one wants to pull through. If I
understand it correctly, that would imply that the rule "an object is
defined iff all of its constituent subobjects are defined" would no longer
hold.)

With default initialization, the situation is more difficult - because it
applies to a wider range of cases - and easier - because there was no
"prior art" from previous implementations to support.

Again, for similar reasons as above, a certain situation - default initia-
lization of module variables - was seen as problematic. But:

> One could possibly special-case the behavior for module variables, but
> the standard doesn't. Instead of special-casing the behavior, the
> standard prohibits the situation where the "normal" behavior causes
> "issues".


....and that's the point: Why special-case explicitly initialized variables
with regard to SAVE, but instead of doing the same in the case of the
module variable with default initialization, put the onus on the programmer
instead of the processor? That's inconsistent to me. It's still special-
casing - but one that exacerbates (IMO) the problem, instead of solving it.
Why not make the behaviour of a non-SAVED default-initialized module variable
implementation-dependent instead? (No need to answer 8-)...)

Jan

Richard E Maine

2006-01-31, 7:02 pm

I think we've beat the original question to death, so this isn't
furthjer comment on that. But on a separate isssue.

Jan Vorbrüggen <jvorbrueggen-not@mediasec.de> wrote:

> We have three different kinds of initialization:
>
> - default
> - explicit
> - run-time (i.e., by executable statements)
>
> The first two are syntactic sugar, as they can both be (and, in some cases,
> under the hood must be) implemented by using the third.


No they are not syntactic sugar and cannot be implemented using
executable statements. If you think so, then you are missing important
points about them. I have heard people vehemently arguing for new
versions of them that are syntactic sugar for things that can be done
with executable statements (namely defining explicit initialization of
unsaved variables to happen on each entry to a procedure), but the
features actually in the standard are important functionality that
cannot be easily duplicated.

The case of explicit initialization is a classic. Can you show me a
standard-conforming way for a subroutine to count the number of times it
has been called without using explicit initialization and without
relying on outside "help"? If there is a way, it sure must be a tricky
one. Now counting invocations is a moderately rare requirement (not
unheard of, but moderately rare). But the special case of needing to
know whether this is the first invocation is *VERY* common. My own code
is littered (as some might describe it :-)) with snippets like

logical, save :: initialized == .false.
...
if (.not. initialized) then
...
! Various stuff which can include far more than just defining
! some varioable values. We might be opening files or doing
! all kinds of other setup work.
...
initialized = .true.
end if

As for default initialization, note that it was added in f95. There were
*VERY* few new features added in f95. F95 was primarily corrections and
clarifications of things that arose as f90 interpretations. There might
have been justification for calling f95 something more like f90 release
2. There is a reason that default initialization was added in f95. In
fact, it was probably the single highest priority new feature of f95. It
didn't get that high priority by being syntactic sugar. The reason is
that people discovered that some quite basic things could not be done
"reasonably" in f90. Notably, the f90 sample implementation of the ISO
varying string module leaks memory to the extent that it is essentially
unusable except on a compiler that does garbage collection to clean up
the "garbage" that is left behind. The ISO varying string module is just
a "canonical" example of a problem that hits just about any attempt to
define operations on types that have pointer components.

Admitedly, allocatable components are probably a "better" solution in
most cases. But that partly because allocatable components act an awful
lot like a form of default initialization. It isn't called default
initialization and you can't use the same syntax to indicate it. In
fact, there is no syntax to control it at all; you get it whether you
want it ot not. (I happen to think it would be natural to at least allow
the =>null() form as an explicit confirmation, but the standard doesn't
do that).

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
James Van Buskirk

2006-01-31, 7:02 pm

"Brooks Moses" <bmoses-nospam@cits1.stanford.edu> wrote in message
news:43DF164E.60100@cits1.stanford.edu...

> If the programmer fails in this duty by omitting the SAVE, then the
> result becomes undefined behavior, and the compiler can do what it
> wants, which generally tends to be "pretend that the programmer had
> included the SAVE" because that's by far the easiest thing to do.


I claim that this statement is inaccurate in that there is one
thing the compiler must do so requested by the programmer: since
omitting the SAVE attribute violates a constraint imposed by the
standard, the compiler must be capable of reporting the violation.
Richard, could you comment on this point, please? Even so terse
a comment as 'yes' or 'no' would be more helpful than you can know.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Richard E Maine

2006-01-31, 7:02 pm

James Van Buskirk <not_valid@comcast.net> wrote:


> since
> omitting the SAVE attribute violates a constraint imposed by the
> standard, the compiler must be capable of reporting the violation.
> Richard, could you comment on this point, please? Even so terse
> a comment as 'yes' or 'no' would be more helpful than you can know.


Yes, a compiler must have that capability. It might be turned off by
default, but the capability must be there.

Strangely, just a few hours ago, I was independently contacted by a
compiler vendor relating to exactly that point. Apparently some user
failed to find that constraint in f95 (it is there) and bitched about
having the error message, while another user bitched about not having
the error message as required by the standard.

The coincidence makes me wonder how independent these events really are.
It isn't as though that constraint very often comes up in discussions.

--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com