Version Intel® Fortran Compiler version 18.0 and newer
Product Intel® Parallel Studio XE
Operating System Windows*, Linux*, macOS*
Architecture IA-32, Intel64
Reading from a variable before it has been written to can result in application errors that are not reproducible and can be difficult to debug, especially for global variables and variables passed as procedure arguments. The Intel® Fortran Compiler version 18 and newer can detect accesses to a wide variety of uninitialized floating-point variables. (The feature is also available in earlier Intel compilers with some restrictions.) This is achieved by initializing such floating-point data to a signaling NaN and then trapping the floating-point invalid exception that occurs if the data are used in a floating-point operation before they have been assigned a value by the application.
Method The application should first be compiled and run with the options /fpe:0 /traceback (Windows) or -fpe0 -traceback (Linux or macOS) to ensure there are no unexpected floating-point exceptions from other sources. If there are, these should be corrected.
Next, compile the application with the options /Qinit:snan,arrays /traceback (Windows) or -init=snan,arrays -traceback (Linux or macOS). This automatically sets /fpe:0 (Windows) or -fpe0 (Linux or macOS), which causes floating-point exceptions to be trapped. The “traceback” switch causes any such exceptions to be followed by a lightweight traceback that includes the procedure name, file name and line number where the exception occurred. If the exception results from an operation on an uninitialized floating-point variable, you will typically see the message:
forrtl: error (182): floating invalid - possible uninitialized real/complex variable.
If the “arrays” argument is omitted, uninitialized scalars will be detected, but uninitialized array elements will not.
In general, the following classes of REAL, COMPLEX, INTEGER, or LOGICAL variables of any KIND are supported:
with the following restrictions:
Warning /Qinit:snan (Windows) or -init=snan (Linux or macOS) unmasks floating-point exceptions so that use of SNaNs in a floating-point operation will be detected and trapped. If you build with optimization, the compiler may speculate floating-point operations, assuming the default floating-point environment in which floating-point exceptions are masked. When you add /Qinit:snan (-init=snan), this speculation may result in exceptions that now get trapped.
The simplest way to avoid this is to reduce the optimization level to /O1 or /Od (-O1 or -O0) when doing uninitialized variable detection. If you wish to maintain optimization, you should add the switch /Qfp-speculation:safe (-fp-speculation=safe) to disable speculation, if there is a possibility that the speculation may cause a floating-point exception.
Another possibility is to add the switch /fp:strict (-fp-model strict), which tells the compiler not to assume the default floating-point environment, but this is likely to have a bigger impact on performance than /Qfp-speculation:safe (-fp-speculation=safe).
Example (Source code at the end of the article)
Whilst it’s usually a good idea to compile with –O0 (Linux or macOS) or /Od (Windows) when debugging, this is not required for uninitialized variable detection. First, make sure the application runs without floating-point exceptions:
$ ifort -O0 -fpe0 -traceback uninitialized.f90; ./a.out 0.0000000E+00 -8.7806177E+13 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 1.000000 1.000000 0.0000000E+00 2.000000 0.0000000E+00 0.0000000E+00 3.000000 0.0000000E+00 0.0000000E+00 0.0000000E+00 1.1448686E+24 0.0000000E+00
No floating-point exceptions, but one or two strange-looking values.
Next, look for uninitialized scalars.
$ ifort -O0 -init=snan -traceback uninitialized.f90; ./a.out NaN NaN 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 1.000000 1.000000 0.0000000E+00 2.000000 0.0000000E+00 0.0000000E+00 3.000000 NaN 0.0000000E+00 0.0000000E+00 1.1448686E+24 0.0000000E+00 forrtl: error (182): floating invalid - possible uninitialized real/complex variable. Image PC Routine Line Source a.out 0000000000405224 Unknown Unknown Unknown libpthread-2.17.s 00007F4032803130 Unknown Unknown Unknown a.out 0000000000403C61 sub_ 39 uninit.f90 a.out 000000000040418A MAIN__ 62 uninit.f90 a.out 0000000000403622 Unknown Unknown Unknown libc-2.17.so 00007F4032250AF5 __libc_start_main Unknown Unknown a.out 0000000000403529 Unknown Unknown Unknown Aborted (core dumped)
Here we see otherwise uninitialized scalars being initialized to a NaN. The access to the module variable AM at line 39 results in an exception, diagnostic and traceback.
Next, look also for uninitialized arrays.
$ ifort -O0 -init=snan,arrays -traceback uninitialized.f90; ./a.out NaN NaN NaN NaN NaN NaN 1.000000 1.000000 NaN 2.000000 NaN NaN 3.000000 NaN NaN NaN NaN NaN forrtl: error (182): floating invalid - possible uninitialized real/complex variable. Image PC Routine Line Source a.out 000000000040AB64 Unknown Unknown Unknown libpthread-2.17.s 00007F903EA5B130 Unknown Unknown Unknown a.out 0000000000403BED sub_ 36 uninit.f90 a.out 0000000000404278 MAIN__ 62 uninit.f90 a.out 0000000000403662 Unknown Unknown Unknown libc-2.17.so 00007F903E4A8AF5 __libc_start_main Unknown Unknown a.out 0000000000403569 Unknown Unknown Unknown Aborted (core dumped)
Array elements that are not explicitly initialized by the application are also being initialized to a NaN. The access to the automatic array F at line 36 results in an exception, diagnostic and traceback. Although the uninitialized variable is not identified by name, the source file and line number make it easy to find. If the application is compiled with -g (Linux or macOS) or /Zi (Windows), it also possible to use a symbolic debugger: when the debugger breaks at the floating-point exception, the variable contents may be examined directly.
! ============================================================== ! ! SAMPLE SOURCE CODE - SUBJECT TO THE TERMS OF SAMPLE CODE LICENSE AGREEMENT, ! http://software.intel.com/en-us/articles/intel-sample-source-code-license-agreement/ ! ! Copyright 2015 Intel Corporation ! ! THIS FILE IS PROVIDED "AS IS" WITH NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT ! NOT LIMITED TO ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR ! PURPOSE, NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS. ! ! =============================================================== module mymod integer, parameter :: n=100 real :: am real, allocatable, dimension(:) :: dm real, target, dimension(n) :: em real, pointer, dimension(:) :: fm end module mymod subroutine sub(a, b, c, d, e, m) use mymod integer, intent(in) :: m Real, intent(in), dimension(n) :: c Real, intent(in), dimension(*) :: d Real, intent(inout), dimension(*) :: e Real, automatic, dimension(m) :: f Real :: a, b print *, a,b,c(2),c(n/2+1),c(n-1) print *, d(1:n:33) ! first and last elements uninitialized print *, e(1:n:30) ! middle two elements uninitialized print *, am, dm(n/2), em(n/2) print *, f(1:2) ! automatic array uninitialized e(1) = f(1) + f(2) em(1)= dm(1) + dm(2) em(2)= fm(1) + fm(2) b = 2.*am e(2) = d(1) + d(2) e(3) = c(1) + c(2) a = 2.*b end program uninit use mymod implicit none Real, save :: a Real, automatic :: b Real, save, target, dimension(n) :: c Real, allocatable, dimension(:) :: d Real, dimension(n) :: e allocate (d (n)) allocate (dm(n)) fm => c d(5:96) = 1.0 e(1:20) = 2.0 e(80:100) = 3.0 call sub(a,b,c,d,e(:),n/2) deallocate(d) deallocate(dm) end program uninit
Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.
Notice revision #20110804