Q.DU
Q.DU

Reputation: 21

Why Fortran's array is initialized to zero automatically in Visual Studio? But when we do some manipulation to it, it won't be initialized auto?

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

Answers (1)

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

Related Questions