Premature finalization of function return value - fortran

I have a derived type t_file with a finalization routine close which simply writes "Finalization" to the screen.
There is also a function returning an instance of the type t_file.
The output of this program is
Finalization.
Finalization.
Just opened
2000
Done.
I have two questions:
Why does the finalization occur before the Just opened output?
Why does the finalization occur twice?
My compiler is Intel(R) Visual Fortran Composer XE 2011 12.1.3526.2010.
Here is the code:
module m_file
implicit none
type t_file
integer::iu=1000
contains
final::close
end type
contains
function openFile() result(f)
implicit none
type(t_file)::f
f%iu = 2000
end function
subroutine close(this)
implicit none
type(t_file)::this
write(*,*) 'Finalization.'
end subroutine
end module
program foo
use m_file
implicit none
type(t_file)::f
f = openFile()
write(*,*) 'Just opened'
write(*,*) f%iu
write(*,*) 'Done.'
read(*,*)
end program

This behaviour surprised me too. I've been getting to grips with Fortran's new(-ish) OO features but haven't yet needed to write final procedures. I think that I can provide an explanation, of sorts, for this behaviour.
On p282 of Modern Fortran Explained the authors write:
When a finalizable object is about to cease to exist (for example, by
being deallocated or from execution of a return statement), the final
subroutine is invoked with the object as its actual argument. This
also occurs when the object is passed to an intent out dummy
argument, or is the variable on the left-hand side of an intrinsic
assignment statement. In the latter case, the final subroutine is
invoked after the expression on the right-hand side has been
evaluated, but before it is assigned to the variable.
It looks to me as if you are hitting both of the two cases mentioned in this paragraph. You get the first Finalization when the entity named f inside the function openFile is about to go out of scope on return from that function.
You get the second Finalization when the variable f in the program scope is used on the lhs of the assignment f = openFile().
From all of this I conclude that you are not seeing premature finalisation of f in the program scope, but something subtly different.
I'm not entirely convinced that this is what is happening, and I cannot think of a good reason why the language's behaviour should be as it is. I'm a bit surprised, now that I've looked into it, that you don't get a third Finalization message as the program ends and f goes out of scope.
With any luck a real Fortran guru will come past soon and enlighten us all.

Minor correction to answer given by High Performance Mark: The first finalization is actually the variable f in the program scope. This can be seen simply by having the final routine print this%iu and setting f%iu in the program scope to some arbitrary value.

Related

How does Fortran handle optional arguments and strings? [duplicate]

I have a FORTRAN code with a routine:
SUBROUTINE READ_NC_VALS(NCID, RECID, VARNAME, VARDATA)
integer ncid, recid
character*(*) varname
real*8 vardata
dimension vardata(15,45,75)
etc.
I want to add some flexibility to this code, and I thought I would do it by first adding an optional flag argument:
SUBROUTINE READ_NC_VALS(NCID, RECID, VARNAME, VARDATA, how_to_calculate)
! everything the same and then ...
logical, optional :: how_to_calculate
Now, at this point, I am not even using "how_to_calculate". I am just putting it into the code for testing. So I compile the code without a hitch. Then I run it, and I get an error in the subroutine. Specifically, some of the values in the code later on are "magically" altered from what they were without that optional argument. The new values don't make sense to the logic of the code, so it exits politely with an error message. Let me stress again that at this point, I am not even using this optional argument. So then, on a lark, I go back to all the places in the source that call this routine and, even though my new argument in optional, I put in values for it in all the calls. When I do that, the code runs fine. So, what's up? How can the mere presence of an unused optional argument in a subroutine result in other data being corrupted? And how can adding input parameters for this optional argument fix things again? This is being compiled with PGI, by the way.
Any ideas? Thanks.
BTW, sorry for not providing more code. My boss might not be too happy with me if I did that. I don't make the rules; I just work here.
Optional arguments in Fortran are implemented by passing 0 (a null pointer) for each optional argument that has no value provided by the calling subroutine. Because of this subroutines that take optional arguments have to:
either have an explicit INTERFACE definition inside the calling subroutine
or be a module-level subroutine (for them interfaces are generated automatically)
If you add an optional argument to a subroutine but it neither has an interface in the caller or is not a module-level subroutine, then the compiler will not generate the right calling sequence - it will pass less arguments than expected. This could pose a problem on Unix systems, where PGI passes the length of all CHARACTER*(*) arguments at the end of the argument list (on Windows it passes the length as the next argument after the address of the string). One missing argument would shift the length arguments placement in the stack (or put them in the wrong registers on x64) leading to the incorrect length of the VARNAME string being received by READ_NC_VALS. This could lead to all sorts of ill behaviour, including overwritting memory and "magically" changing values that should not change according to the program logic.
Obviously, just adding a dummy argument to a subroutine, with or without the optional attribute, shouldn't cause any problems. What might happen, though, is that the change exposes some other problem with the code, which was already there, but didn't cause any visible bad effects.
Without any more code, all we can do is guess, which usually isn't really useful.
One thing that pops into mind is the necessity of an explicit interface, when using optional arguments. Is the code organized into modules?

Distinguishing between a variable and a constant

Okay, before I start: I know this is really bad. I'm asking for a hack for a situation that wouldn't have eventuated if there had been a design agreement that everyone followed. But here is my problem.
I have an enormous Fortran code base with an error reporting routine. The error reporting routine is only called if something weird happened, and it has an integer input: ErrorCode. Positive values mean errors and abort, negative values mean warnings and continue.
Here's my problem:
Some people have taken to call the error reporting function like this:
ErrorCode = -5
call error_report(ErrorCode)
if (ErrorCode /= 0) stop "Hey, you were supposed to reset ErrorCode"
I don't know whether there is any call to that error_report that actually expects a negative ErrorCode to be reset to 0. All I know is that the current implementation of error_report does this, and I don't want to change any functionality.
And other people make it easier on themselves:
call error_report(-5)
At the moment, in the routine, ErrorCode is not declared with any INTENT, just so that the code compiles. But of course this only means that whenever a warning is called in the second way, instead of displaying the warning and keeping working, the program segfaults.
I have neither the time nor the authority at the moment to clean up the code properly (normally I'd just set it to INTENT(INOUT) and then let the compiler tell me where I need to make changes. But this is not an option at the moment for a variety of reasons.)
Is there any way in which I could write a routine error_report that would satisfy both versions? Procedure Overloading? Some method to distinguish between a variable and a constant? Anything?
Here is an idea that should work on any *nix system... The main idea is that constant literals are compiled into the binary as symbols, whereas variables are not.
So if you are using ld for linking, it will insert a symbol _end at the final position (for both static and dynamic linking).
This you can (ab)use to check whether a given dummy argument has an address before or after _end. In case of a lower address, the actual argument is a constant, otherwise it is a (temporary) variable.
This, however requires some C code:
addr.c
int isConstant(int *x){
extern void *_end;
if ( (void *)x > (void *)&_end ) {
return 1; // Variable
} else {
return 0; // Constant
}
}
test.F90
program test
use,intrinsic :: ISO_C_Binding
interface
integer(C_INT) function isConstant(a) bind(C, name="isConstant")
use,intrinsic :: ISO_C_Binding
integer(C_INT), intent(in) :: a
end function
end interface
integer :: i
integer,parameter :: ii=2
i = 1
print *,isConstant(i)
print *,isConstant(1)
print *,isConstant((i))
print *,isConstant(ii)
end program
Compile it as
gfortran -Wall -Wextra test.F90 addr.c
It will give you:
./a.out
1
0
1
0
Note that I did not test this with Windows Tested on Windows using mingw. Use at your own risk.
Please note that the constant expression (i) is not definable as per Standard. However, it is created at runtime, and therefore not a symbol. This is apparent in the output.
However, in the context of the OP, I did not get a segfault when trying to assign it a value.

Is It Necessary to declare the Type of User-Defined Functions in ANY Calling Routine?

I use the Intel Visual Fortran. According to Chapmann's book, declaration of function type in the routine that calls it, is NECESSARY. But look at this piece of code,
module mod
implicit none
contains
function fcn ( i )
implicit none
integer :: fcn
integer, intent (in) :: i
fcn = i + 1
end function
end module
program prog
use mod
implicit none
print *, fcn ( 3 )
end program
It runs without that declaration in the calling routine (here prog) and actually when I define its type (I mean function type) in the program prog or any other unit, it bears this error,
error #6401: The attributes of this name conflict with those made accessible by a USE statement. [FCN] Source1.f90 15
What is my fault? or if I am right, How can it be justified?
You must be working with a very old copy of Chapman's book, or possibly misinterpreting what it says. Certainly a calling routine must know the type of a called function, and in Fortran-before-90 it was the programmer's responsibility to ensure that the calling function had that information.
However, since the 90 standard and the introduction of modules there are other, and better, ways to provide information about the called function to the calling routine. One of those ways is to put the called functions into a module and to use-associate the module. When your program follows this approach the compiler takes care of matters. This is precisely what your code has done and it is not only correct, it is a good approach, in line with modern Fortran practice.
association is Fortran-standard-speak for the way(s) in which names (such as fcn) become associated with entities, such as the function called fcn. use-association is the way implemented by writing use module in a program unit, thereby making all the names in module available to the unit which uses module. A simple use statement makes all the entities in the module known under their module-defined names. The use statement can be modified by an only clause, which means that only some module entities are made available. Individual module entities can be renamed in a use statement, thereby associating a different name with the module entity.
The error message you get if you include a (re-)declaration of the called function's type in the calling routine arises because the compiler will only permit one declaration of the called function's type.

Creating a simple subroutine in fortran

I am new to Fortran and I had made a program where everything did fit into one single file, which worked.
However when i tried to take out parts and put them into modules and subroutines I quickly ran into problems.
Even after removing everything and having only the bare minimum left, it still gives an error regarding the subroutine.
Currently the heavily reduced main program looks like this. It only uses the module and calls the subroutine.
program test
use mod1
call sub1(var)
end program test
and the module looks like:
Module mod1
implicit none
type A
real :: type1
end type A
contains
subroutine sub1(var)
type(A) :: var
var%type1 = 1+1
end subroutine sub1
However I seem to do something wrong here and unfortunately I can not figure out what. I get the error
||Error: Type mismatch in argument 'var' ; passed REAL(4) to TYPE(a)|
end module mod1
Can someone please explain which fundamental mistake I am making in order to prevent the most basic subroutine from working?
In your program you do not explicitly declare var. In days of yore Fortran supported implicit typing and, by default, variables whose name begin with a v will be of type real. Fortran retains this capability, though its use is now frowned upon.
I think you are thinking (as if I had a clue what you are thinking) that var in the program scope will somehow be automatically associated with, or the same as, var in the subroutine in the module. It won't be.
Do these things:
Insert implicit none on the line after use mod1 in your program.
Explicitly declare var within the program, eg type(a) :: var

Use function inside subroutine in FORTRAN77

I am updating legacy code and I need to use a simple mathematical function inside a subroutine. I cannot figure out how to do this. I have a function that works when called from a test program. What do I need to do differently for a subroutine?
example:
subroutine foo(i,j,k)
i = bar(j,k)
stuff = otherstuff
return
end
other info:
bar is an erf approximation.
I am using the PGF90 compiler.
I am new to FORTRAN from C.
thanks!
Basically, calling from a program or a subroutine shouldn't differ. Does the code really look like this, without any declarations? This means all variables will have implicit types: variables with names starting with the letters i-n will be integer, all others real; this also holds for function return values. The code you show, tries to assign a real (bar()) to an integer (i).
If you're writing new code, always start programs and procedures with IMPLICIT NONE. This forces you to explicitly include type declarations for all variables and function return values, greatly reducing errors.