Some type of automatic initialization of variables?

I’m porting a 32 bit Fortran program (on a CENTOS 7 computer) to a 64 bit (RHEL 7) computer. I’ve noticed variables that were automatically initialized to -0.000000 on the 32 bit machine are -nan on the 64 bit machine.

These variables aren’t being initialized by statements in the program.

My guess is these variables probably are automatically being set by the gfortran compiler on the 32 bit machine.

Question: What practical things can I do about this?

You should not rely on “automatic” initialization of variables, initialize them explicitly to zero if needed.

1 Like

You are fortunate that the uninitialized numbers are NaN because this allows you to identify them and fix the fortran source code. When uninitialized variables have random bits, they are much harder to locate and correct. Some compilers have options to set unitialized values to specific values. NaN is a good choice for floating point variables. Integers can be set to large positive or negative values, which makes it easier to locate when they are used, for example, as an array index. Some compilers have options to flag unitialized entities when they are first used.

No other way to say this but relying on the compiler/OS to initialize anything by default (unless you are using a compiler option to do it) is shoddy programming.The results can be compiler dependent.

Try this program on your systems.

Program realz
  
  USE ISO_FORTRAN_ENV

  Implicit NONE

  Real(REAL32) :: z32
  Real(REAL64) :: z64

  Print *,''
  Print *,' uninitialized'

  Print *,' z32 = ? - ', z32
  Print *,' z64 = ? - ', z64

  z32 = -0.000000
  z64 = -0.000000

  Print *,''
  Print *,' z32 = -0.000000 - ', z32
  Print *,' z64 = -0.000000 - ', z64

  z32 = -0.000000_REAL32
  z64 = -0.000000_REAL64

  Print *,''
  Print *,' z32 = -0.000000_REAL32 - ', z32
  Print *,' z64 = -0.000000_REAL64 - ', z64

  z32 = REAL(-0,REAL32)
  z64 = REAL(-0,REAL64)

  Print *,''
  Print *,' z32 = REAL(-0,REAL32) - ', z32
  Print *,' z64 = REAL(-0,REAL64) - ', z64
  Print *,''
  Print *,''

  STOP

End Program realz

I get the following results for ifort, gfortran-11, and nvfortran on a Linux Mint (Ubuntu 18.04 LTS) 64 bit system. Only ifort appears to initialize to 0.0 by default but that just might be an optimization thing so don’t assume ifort does this for all unitialized values.

ifort OneAPI 2021.6.0

  uninitialized
  z32 = ? -   0.0000000E+00
  z64 = ? -   0.000000000000000E+000
 
  z32 = -0.000000 -   0.0000000E+00
  z64 = -0.000000 -   0.000000000000000E+000
 
  z32 = -0.000000_REAL32 -   0.0000000E+00
  z64 = -0.000000_REAL64 -   0.000000000000000E+000
 
  z32 = REAL(-0,REAL32) -   0.0000000E+00
  z64 = REAL(-0,REAL64) -   0.000000000000000E+000

gfortran-11

  uninitialized
  z32 = ? -    6.41672678E+27
  z64 = ? -    0.0000000000000000     
 
  z32 = -0.000000 -   -0.00000000    
  z64 = -0.000000 -   -0.0000000000000000     
 
  z32 = -0.000000_REAL32 -   -0.00000000    
  z64 = -0.000000_REAL64 -   -0.0000000000000000     
 
  z32 = REAL(-0,REAL32) -    0.00000000    
  z64 = REAL(-0,REAL64) -    0.000000000000000

nvfortran 22-2-0

  uninitialized
  z32 = ? -    4.5916347E-41
  z64 = ? -    1.1520304496612931E-310
 
  z32 = -0.000000 -    -0.000000    
  z64 = -0.000000 -    -0.000000000000000     
 
  z32 = -0.000000_REAL32 -    -0.000000    
  z64 = -0.000000_REAL64 -    -0.000000000000000     
 
  z32 = REAL(-0,REAL32) -     0.000000    
  z64 = REAL(-0,REAL64) -     0.000000000000000

1 Like

You can define variables in fortran in the declaration statement or in an assignment statement. If you do the former, then you should add the SAVE attribute to make clear what is happening. Which of those choices is appropriate depends on how the variables are used, sometimes one is appropriate and sometimes the other. Of course, all variables should be defined to appropriate values before they are used. That is why the original NaN values are so useful, they help the programmer identify the mistakes in the fortran code. A good time to fix the code is when it is still running “correctly” on the old compiler and OS. Then you can print out intermediate results to help locate where uninitialized variables are being referenced. If you only have the buggy code, and you can only compile it on a machine that does not allow any command-line default initializations, then it is much harder to debug the code.

valgrind will detect some uninitialized variables. It probably won’t detect variables initialized by the compiler to default values.