- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to determine what the default "SAVE" behavior is for Intel Fortran. I think I have it, but would like a second opinion!
I look at this description of "SAVE" attribute:
http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/win/compiler_f/lref_for/source_files/rfsave.htm
On that page, it states that certain variables are saved by default, including "Non-scalar local variables of non-recursive subprograms". To me this means locally declared plain arrays with no extra attributes (such as AUTOMATIC, ALLOCATABLE, assumed shape, etc.). In the meantime, the ifort manage says this:
-auto-scalar
Causes allocation of scalar variables of intrinsic types INTEGER, REAL,
COMPLEX, and LOGICAL to the run-time stack. This is the default. However,
if you specify -recursive or -openmp, the default is -automatic.
You cannot specify -save, -auto, or -automatic with this option.
-save Places variables, except those declared as AUTOMATIC, in static memory
(same as -noauto or -noautomatic). The default is -auto-scalar. However,
if you specify -recursive or -openmp, the default is -automatic.
-automatic
Causes all local, non-SAVEd variables to be allocated on the run-time
stack (same as -auto or -nosave). The default is -auto-scalar. However,
if you specify -recursive or -openmp, the default is -automatic.
So from this information, I come to the following conclusions. Are these somewhat accurate?
1. The run-time stack is likely a standard LIFO (presumably at the end of the process heap on Linux/Unix). Very dynamic, not static. When the running program encounters a RETURN or END statement within the currently running subprogram, it exits this subprogram, and the subprogram's stack data becomes unusable, irrelevant, and likely to be overwritten. By default, this stack will contain locally declared/allocated scalar variables (of the four aforementioned types, above), and *not* contain arrays.
2. The "static memory" refers to a static address within the user process. This is where saved data is located, and remains there until the process terminates. The static location for a particular subprogram is exclusive and protected from being inadvertently accessed by other subprograms (ie. except for parameters in a call, a programmer pointer error, etc.). When a subprogram gets called a second time (no recursion), the saved data in its "static memory" contains the same values it had when it last RETURNed/ENDed.
Whaddaya think? Am I close?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Conversely, writing programs to depend on the specifics of a particular compiler implementation can make the code non-portable. One day, IFort may revamp its implementation details, and possibly invalidate any Fortran codes which depend on non-portable properties.
I suppose my answer is comparable to the one that was given to a prospective buyer of a yacht when he asked about the price. In other words, if you really must ask about such details, you would be reading the documentation instead of asking here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When I first saw your post, I wondered if you were about to ask why certain recent ifort versions don't have default SAVE properties for arrays declared in Fortran main program. That used to be a common treatment, many compilers doing that in main where it was not the default for subroutines. No, I didn't consciously write code which depends on it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We are dealing with ancient code, and we're just trying to understand the behavior of this particular compiler, what it chooses to do by default. We see subroutines that rely on arrays being saved by default with no explicit SAVE statement. Gave us a scare, so we want to know what the compiler has been doing with its generated code all these years. Did we get lucky?
So we just need to understand behavior. Inspecting the documentation gave us some confidence, but the manpage is oblique. It only mentions where data is placed, but it does not state whether anything is saved! Also, compilers and documentation do not always agree, so I just wanted to clarify that SAVEd data is placed in static locations (presumably safe) and anything placed in a stack is history. I'm dealing with scientists and physicists and I need to be explicit and exact with the manpage and how it may (or not) agree with the doc on the SAVE attribute.
The standard is clear and we rely on compiler vendors to adhere to it. Like you, I don't write code that way. I've spent time inside a Fortran compiler, and I discourage relying on default behavior.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It turns out this has been going on for years using ifort. We just discovered the missing SAVE, it was an omission in one routine. Now, inserting the SAVE causes no change in results from the ifort-generated code. Same source code on a different compiler behaves differently between a SAVE statement and its absence. We hope to attain some confidence in what ifort has been doing all this time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If so, those variable(s) acquire the SAVE attribute as a consequence, and this feature is completely in agreement with the language standard.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Acutally this is more of a case of the original programmer getting lucky.
For certainty, you will have to walk through the code to find ambiguities.
If you look through this forum messages you might find references to a FORTRAN Lint program.
The IVF uninitialized variables diagnostic might not catch all such errors.
Your latent bugs can include instances of where a variable must be on stack .AND. initialized by prior use. IOW your program is relying on persistance of data on stack between calls to a subroutine.
subroutine foo
call zebra ! accidentally or by design inits stack data then returns
call xray ! relies on zebra stack whack
...
call xray ! relies on data carryover from prior xray
...
end subroutine foo
Then sometime later you add
subroutine foo
call zebra ! accidentally or by design inits stack data then returns
call xray ! relies on zebra stack whack
CALL DoodlyDoo
...
call xray ! relies on data carryover from prior xray
...
end subroutine foo
And find the 2nd call to xray now fails
These programming "works by accident" situations are very difficlult to identify.
Also, the correct fix to the problem may not be simply as adding SAVE
Consider what to do when the above CALL DoodlyDoo calls a subroutine containing a series of calls to xray?
Walk your code. I suspect thereis more than one instance where the program is "standing on thin ice".
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see three possibilities:
1. Luck had nothing to do with it. As others have mentioned, there are cases in the standard where SAVE attribute is implied without appearing explicitly, and there are cases where values are expected to be retained between execution even though the SAVE attribute does not apply. You would have to examine your code more closely to see if any of these cases apply to you.
2. You "got lucky," but by design. Essentially all of the early mainframe FORTRAN compilers used static storage for everything. Some rarely used features (like the use of code overlays to minimize memory usage) could cause variables to lose there values between executions of a subprogram, but at a practical level these compilers appeared to SAVE variables even though the standard did not guarantee their values would be retained. As compiler writers began to work in more varied storage environments, they were faced with the problem of what to do with old programs (and old programmers) that assume variables are SAVEd without explicit declaration. Rather than engaging in fruitless fights with programmers that only think they know Fortran, many compilers will, by default, emulate the behavior of those old compilers on old programs. The details can get messy, but one way to look at it would be that if a program unit contains nothing that could not have been written in standard FORTRAN 77, and if the program unit contains no SAVE statement, many compilers will save its variables anyway. If this case applies to you, and if the program is still being modified, I would encourage you to try to add the missing SAVE statements, but it probably is not urgent that you do so, as updates to the compiler will likely preserve this support for old programs.
3. You "got lucky," quite possibly by accident of implementation. Nominally, variables allocated on the stack could be at a different address for each execution of the subprogram in which they appear, but in practice there are many common program structures that lead to them getting the same "dynamic" address each time. This doesn't guarantee value retention, but if there is no intervening use of that storage for some other purpose, the variables effectively appear to have been SAVEd. This kind of value retention can be robust in the sense that it will continue in the face of minor program modifications and recompilations, but can be quite fragile in the face of larger program modifications or changes in compiler defaults (especially those that change what does and does not go on the stack), so here I would encourage you to put a high priority on adding the SAVE statements necessary to express the semantics you mean.
-Kurt
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am a strong advocate of placing into your sorce code attributes that enforce the storage placement requirements of the program. To rely on unseen compiler options opens yourself or the next software support engineer to hours or days of unnecessary work in tracking down a fleeting bug.
In addition to deciding if the orignial program should have used SAVE or not, or marked the function/subroutine as RECURSIVE, there are other pending issues that you may be faced with. In particular for situations where you are updating a program from single threaded to use parallel constructs. In these situations what works as SAVE variables in serial may break when run in parallel. This said, fix the serial code first, then address the parallel issues.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The compiler, by default, allocates non-scalars in static storage and scalars are in non-static storage (unless they are given SAVE semantics.)
If you want SAVE, say SAVE.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page