Reputation: 21
Recently, I met a bug caused by automatic initialization of Fortran's array (by IDE Visual Studio). So I coded a simple routine to give it a test :
SUBROUTINE test
IMPLICIT NONE
INTEGER :: a, u(2)
a = 1
WRITE(*,'(a,2i5)') 'original :', u(1), u(2)
u(1) = a + 1
WRITE(*,'(a,2i5)') 'after manip :', u(1), u(2)
END SUBROUTINE test
If we call this subroutine two times, like:
PROGRAM main
IMPLICIT NONE
INTEGER :: i
DO i=1,2
CALL test
END DO
END PROGRAM main
we will have the output like:
original : 0 0
after manip : 2 0
original : 2 0
after manip : 2 0
So we could find that even without initialization, array in fortran will be set to zero automatically. But if we do something to it's element, this element won't be eliminated from stack when the program quit the subroutine, and will be reserved and reused by the next call. Maybe this question is not of interest because it's recommanded to initialize variable.. But I am just curious of the mechanisme behind and wish exposing it to others Thanks in advance. DU
Upvotes: 1
Views: 649
Reputation: 60058
There is no automatic initialization of local variables that would happen on each call.
All local variables are undefined on each call of the subprogram unless the variable has the SAVE
attribute. That attribute may be assigned implicitly by initializing the variable during the declaration Fortran assignment on declaration and SAVE attribute gotcha
So if a variable is not SAVE
, it is undefined when a subroutine is called. It is invalid to use the value stored in there. There can be anything in there. Because the stack is often lined up the same way when calling the same subprogram, the local variable may happen to be located at the same memory address, as the old value used to be. The old value may still be there, unless it was rewritten by some other subprogram. But it is just a coincidence.
If you want the variable to have some defined value when the subroutine starts, make it SAVE
. However, that can be problematic for recursive subroutines and for threading.
Or define the variable in the first executable statements of the subprogram.
Regarding your title. There is no Fortran in Visual Studio per se. Tehre are several compilers that you may be using. Assuming you are using Intel Visual Fortran, see How to initialize all local variables to zero.
Consider:
PROGRAM main
IMPLICIT NONE
INTEGER :: i
DO i=1,2
CALL test
call test2
END DO
END PROGRAM main
SUBROUTINE test
IMPLICIT NONE
INTEGER :: a, u(2)
logical, save :: called = .false.
if (.not. called) then
called = .true.
u = 0
end if
a = 1
WRITE(*,'(a,2i5)') 'original :', u(1), u(2)
u(1) = a + 1
WRITE(*,'(a,2i5)') 'after manip :', u(1), u(2)
END SUBROUTINE test
SUBROUTINE test2
IMPLICIT NONE
real :: dummy(20)
call random_number(dummy)
call test
END SUBROUTINE test2
resulting in:
> gfortran stack.f90
> ./a.out
original : 0 0
after manip : 2 0
original :32766 0
after manip : 2 0
original :**********
after manip : 2*****
original :32766 0
after manip : 2 0
Or consider this:
call s1
call s2
end
subroutine s1
use iso_fortran_env, only: int64
integer(int64) :: i
i = 2314885733423007048_int64
end subroutine
subroutine s2
character*8 :: ch
print *,ch
end subroutine
output:
> gfortran test2.f90
> ./a.out
HELLO
Upvotes: 4