# Undefined variables

**URL:** <https://fortran-lang.discourse.group/t/undefined-variables/3708>\
**Category:** Help\
**Created:** [June 10, 2022, 6:30am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708 "2022-06-10T06:30:16Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![fortran4r](https://avatars.discourse-cdn.com/v4/letter/f/9de0a6/32.png) [@fortran4r](https://fortran-lang.discourse.group/u/fortran4r)\
**Post date:** [June 10, 2022, 6:30am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/1 "2022-06-10T06:30:16Z")

</div>

```auto
program test
  real(8) :: x1, x2(5)
  real(8), allocatable :: x3(:)
  allocate(x3(5))
  print *, x1
  print *, x2
  print *, x3 
end program

```

Using GFortran 12.1.1, I get random values for x1 and x2 at each run, but x3 remains filled with zeros. How come?

---

<div class="post-metadata">

**Author:** ![mecej4](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mecej4/32/855_2.png) [@mecej4](https://fortran-lang.discourse.group/u/mecej4)\
**Post date:** [June 10, 2022, 7:04am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/2 "2022-06-10T07:04:48Z")

</div>

The variables x1, x2, x3 are being printed out despite their status of ‘undefined’. The behavior of the program is ‘undefined’. Different compilers may print different results.

It is wrong to ask the question “how come?” in such a situation, as far as the Fortran language rules are concerned.

The values being printed out are not predictably random (for x1, x2) or zero (for x3). The values that you see simply happened to be there because some other program put those values into those memory locations.

You can look at the source code of the compiler and libgfortran for the answer, but I think that it is a waste of time to do so.

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [June 10, 2022, 7:11am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/3 "2022-06-10T07:11:38Z")

</div>

The value of a variable is undefined until you initialize it (its bytes may contain non zero values at the start of the program).

An allocatable variable is declared on the heap. Reading quickly the Fortran standard, it does not seem guaranteed that it will always be filled with zeros. Note that in C there is `malloc()` which does not put zeros values and `calloc()` which puts zeros in the allocated zone (and is therefore slower).

Automatically initializing to zero variables that you would later initialize with your own values would be a waste of CPU time.

---

<div class="post-metadata">

**Author:** ![fortran4r](https://avatars.discourse-cdn.com/v4/letter/f/9de0a6/32.png) [@fortran4r](https://fortran-lang.discourse.group/u/fortran4r)\
**Post date:** [June 10, 2022, 7:52am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/4 "2022-06-10T07:52:10Z")

</div>

> [@vmagnin](#):
>
> Automatically initializing to zero variables that you would later initialize with your own values would be a waste of CPU time.

That’s why I hate C++ std::vector.

---

<div class="post-metadata">

**Author:** ![Pap](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pap/32/1305_2.png) [@Pap](https://fortran-lang.discourse.group/u/Pap)\
**Post date:** [June 10, 2022, 8:19am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/5 "2022-06-10T08:19:03Z")

</div>

It might be a good idea to re-run the program, perhaps after some time using the computer. I guess the values printed will be different then. gfortran is supposed to issue a warning for this example with the flag `-Wmaybe-uninitialized`, although I have seen it issuing false positives or not issuing any warning at all, depending on the optimization flag.

---

<div class="post-metadata">

**Author:** ![NormanKirkby](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/normankirkby/32/1091_2.png) [@NormanKirkby](https://fortran-lang.discourse.group/u/NormanKirkby)\
**Post date:** [June 10, 2022, 8:20am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/6 "2022-06-10T08:20:53Z")

</div>

Using, and not using, compiler switches to initialise variables and comparing the results is a sensible precautionary check on new code, there are also compiler and run time checks for the use of variables before they have been assigned values. Thing get worrying when those two approaches yield different issues in the code!

---

<div class="post-metadata">

**Author:** ![Pap](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pap/32/1305_2.png) [@Pap](https://fortran-lang.discourse.group/u/Pap)\
**Post date:** [June 10, 2022, 8:23am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/7 "2022-06-10T08:23:28Z")

</div>

> [@fortran4r](#):
>
> That’s why I hate C++ std::vector

Oh, you have _many_ reasons to hate `std::vector`, `std::array`, and anything related to matrices in C++. Compated to Fortran it’s ridiculously primitive. 🙂

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [June 10, 2022, 9:03am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/8 "2022-06-10T09:03:47Z")

</div>

> [@fortran4r](#):
>
> ```auto
> program test
> real(8) :: x1, x2(5)
> real(8), allocatable :: x3(:)
> allocate(x3(5))
> print *, x1
> print *, x2
> print *, x3 
> end program
> 
> ```

Compiling on WSL2 with `gfortran -g -ffpe-trap=invalid,overflow -finit-real=snan -fbacktrace undef.f90`, as I suggested in a [tweet](https://twitter.com/fortrantip/status/1521100997195669504), and running gives

```auto
(base) /mnt/c/fortran/test$ ./a.out

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.

Backtrace for this error:
#0 0x7f7164504700 in ???
#1 0x7f71645038a5 in ???
#2 0x7f716433720f in ???
#3 0x7f71647442cd in ???
#4 0x7f7164746a2b in ???
#5 0x7f7164746dc5 in ???
#6 0x7f7164747dc6 in ???
#7 0x559ba4cd5325 in test
	at /mnt/c/fortran/test/undef.f90:5
#8 0x559ba4cd54b9 in main
	at /mnt/c/fortran/test/undef.f90:8
Floating point exception

```

---

<div class="post-metadata">

**Author:** ![Sideboard](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/sideboard/32/779_2.png) [@Sideboard](https://fortran-lang.discourse.group/u/Sideboard)\
**Post date:** [June 10, 2022, 9:18am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/9 "2022-06-10T09:18:37Z")

</div>

I didn’t expect that. What is the “arithmetic operation” here? Implicitly converting `snan` into strings to print them? Thought that would be valid for any value.

---

<div class="post-metadata">

**Author:** ![lkedward](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/lkedward/32/72_2.png) [@lkedward](https://fortran-lang.discourse.group/u/lkedward)\
**Post date:** [June 10, 2022, 10:42am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/10 "2022-06-10T10:42:37Z")

</div>

As others have pointed out, anything can happen because the behaviour is undefined with respect to the Fortran standard.

With that said, I think we can still answer your question: my understanding is that since `x3` is dynamically allocated here, it requires a request to the OS for more memory and the OS may zero that memory, or fill with random data, in order to protect information written there by a previous process. You cannot rely on this behaviour because it is implementation specific and repeated allocation/deallocation may simply use memory already allocated to your process.

`x1` and `x2` by contrast are on the stack and hence they likely contain any information left on the stack during the initialisation of the program.

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [June 10, 2022, 12:29pm UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/11 "2022-06-10T12:29:32Z")

</div>

Modifying your program like this:

```fortran
program test
  real(8), allocatable :: x3(:)
  integer :: i

  do i = 1, 50
    allocate(x3(5))
    print *, x3
    deallocate(x3)
  end do
end program

```

I obtain that:

```bash
$ gfortran essai.f90 && ./a.out
   0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000     
   1.1340447011303576E-313 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000     
   1.1340447011303576E-313 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000     
   1.1340447011303576E-313 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
[...]

```

Strangely, in gdb I can see the address is always the same:

```nohighlight
2: &x3 = (PTR TO -> ( real(kind=8), allocatable (5) )) 0x55555555c910

```

So why the `x3(1)` is zero during the first iteration of the loop and non-zero after? 🤔

Each time I run the program the non-zero value is different.

With ifort/ifx, only zeros are printed.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [June 10, 2022, 2:36pm UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/12 "2022-06-10T14:36:01Z")

</div>

> [@lkedward](#):
>
> `x1` and `x2` by contrast are on the stack

Not to forget the Fortran language standard does not get into implementation details and considerations such as variables on the stack vs heap are not relevant to the standard.

The key aspect is **undefined**.and per the standard, it makes it nonconforming to reference an object that is undefined.

The instructions with `PRINT` on lines 5, 6, and 7 in the original post thus do not conform and the program behavior can be viewed as `processor-dependent` or better yet, not to be “read much into”.

---

<div class="post-metadata">

**Author:** ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)\
**Post date:** [June 11, 2022, 2:22am UTC](https://fortran-lang.discourse.group/t/undefined-variables/3708/13 "2022-06-11T02:22:54Z")

</div>

By doing nothing with the values except printing them you  
unfortunately slip through a loop-hole in several compilers  
that ends up basically acting like the variables are never being used,  
so I added a few lines where I added zero to the values to your example  
to reflect that more common case.

If you had done any other operation other than printing on the variables common  
compiler switches that should be used during development  
would have warned this was not standard-conforming code.

For example, if you add zero to the values and compiler with

```bash
gfortran -Wall xx.f90 -o xx
./xx

```

You would have been warned about X1.

If you preset core you can see you had NaN values in  
the static arrays.

If you had set floating point traps it would not have let  
you run using the undefined values.

You should always have on as many debug flags as you can when  
developing. Some people spent a good deal of time writing those  
features because they are so valuable.

At least with gfortran, use -Wall at a minimum whenever  
developing new code unless it causes a massive slowdown (which  
is rare except with very large high-performance codes that  
have long wall-clocks). So just making a simple script that  
uses three sets of compiler switches, each of which can help  
detect different issues:

```auto
#!/bin/bash
#@(#) debug.sh - compiler and run with debug flags
BASE_OPTIONS='
 -fimplicit-none 
 -Wuninitialized 
 -Wextra 
 -Wall 
 -pedantic-errors 
 -fcheck=all 
 -Wimplicit-interface 
 -Wimplicit-procedure 
 -ffree-form 
 -fbacktrace 
 -fmax-errors=3 
'
MORE='
 -finit-real=snan 
 -Wcharacter-truncation 
 -Warray-temporaries 
'
EXTRA='
-ffpe-trap=invalid,zero,overflow
'
set -x
rm -f ./a.out
gfortran -g -O0 $BASE_OPTIONS "$@" && ./a.out
rm -f ./a.out
gfortran -g -O0 $BASE_OPTIONS $MORE "$@" && ./a.out
rm -f ./a.out
gfortran -g -O0 $BASE_OPTIONS $MORE $EXTRA "$@" && ./a.out
exit

```

And using something like your example

```fortran
program test
  real(8) :: x1, x2(5)
  real(8), allocatable :: x3(:)
  allocate(x3(5))
  x2=x2+0
  x3=x3+0
  x1=x1+0
  print *, x1
  print *, x2
  print *, x3 
end program

```

```nohighlight
+ gfortran -g -O0 -fimplicit-none -Wuninitialized -Wextra -Wall -pedantic-errors -fcheck=all -Wimplicit-interface -Wimplicit-procedure -ffree-form -fbacktrace -fmax-errors=3 xx.f90
xx.f90:5:9:

    5 | x1=x1+0
      | ^
Warning: ‘x1’ may be used uninitialized in this function [-Wmaybe-uninitialized]
+ ./a.out
  -1.4614335721641550E+051
   0.0000000000000000 -1.4614335721641550E+051 0.0000000000000000 -1.4614331294416530E+051 0.0000000000000000     
   0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000     

```

Will not catch everything, but you do get a warning x1 is not set

```nohighlight
+ gfortran -g -O0 -fimplicit-none -Wuninitialized -Wextra -Wall -pedantic-errors -fcheck=all -Wimplicit-interface -Wimplicit-procedure -ffree-form -fbacktrace -fmax-errors=3 -finit-real=snan -Wcharacter-truncation -Warray-temporaries xx.f90
+ ./a.out
                       NaN
                       NaN NaN NaN NaN NaN
   0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000     

```

Seeing those NaN values is a red flag and it makes it a lot less likely the  
program will inadvertently run with undefined values.

```nohighlight
+ gfortran -g -O0 -fimplicit-none -Wuninitialized -Wextra -Wall -pedantic-errors -fcheck=all -Wimplicit-interface -Wimplicit-procedure -ffree-form -fbacktrace -fmax-errors=3 -finit-real=snan -Wcharacter-truncation -Warray-temporaries -ffpe-trap=invalid,zero,overflow xx.f90
+ ./a.out

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.

Backtrace for this error:
#0 0x7fa93b23cd21 in ???
#1 0x7fa93b23bef5 in ???
#2 0x7fa93b07020f in ???
#3 0x56334a787319 in test
        at /tmp/xx.f90:5
#4 0x56334a7876b7 in main
        at /tmp/xx.f90:11
fwish: line 27: 708172 Floating point exception(core dumped) ./a.out
+ exit

```

Checking for floating point exceptions stops you early on so you can figure  
out what went wrong.

In some classes I used to teach compiler options were introduced early, with an emphasis on  
a good set of debug switches. One of the most important features a good compiler has is the ability to  
catch errors. New users should always make sure they carefully read the options their compiler has.  
Unfortunately many switches are esoteric and complicated but often mixed in with the more important switches, which seems to put off a lot of people. This results in people using compilers for years without realizing there are really useful switches available.

There has been some discussion lately about new courses being created. I would highly recommend that somewhere in those courses someone discusses switches for debugging, switches for performance/production release, switches for profiling, and switches needed for using a debugger.

I have seen codes released into production running 20% slower than they should; codes with easily detetected bugs being put out in the wild; and so on that a good knowledge of readily available compiler options would have prevented.
