Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Trapping on uninitialized variable use

Scott_L_
New Contributor I
829 Views

 

Using the compiler option to initialize variables to Nan and trap on Nan (uninitialized variable), should this trap on assigning an uninitialzed variable to another variable, or just using it in an arithmetic expression?

When  y is NaN and uninitialized, I don't seem to get an exception with

 

x = y

 

but I do for

x = y + 1.0

 

thanks,

Scott

 

0 Kudos
8 Replies
Steven_L_Intel1
Employee
829 Views

Note that in the current version, only static (SAVEd) variables get initialized. I tried a toy program and got the error. Optimization might do something to the assignment that prevents the error from happening.

0 Kudos
mecej4
Honored Contributor III
829 Views

How the statement x=y is executed may depend on the compiler options used. It is conceivable that copying bytes could be done using purely integer instructions, rather than loading and storing an FPU register (XMM or X87). If so, the NaN would not be caught.

The following program, compiled using /warn:uninit /auto with the 15.0 64-bit compiler, did report a runtime check failure on the third line.

program uninit
real x,y,z
x=y
z=y+1.0
write(*,*)x,y,z
end program

 

0 Kudos
Scott_L_
New Contributor I
829 Views

I am compiling in debug &  noopt.  The variable y in my real application is static in the main program, and passed as an argument to a subroutine.  In the subroutine, x = y does not trap but x = y - something does not. 

 

 

0 Kudos
Steven_L_Intel1
Employee
829 Views

An example would be helpful. Here's what I tried:

C:\Projects>type t.f90
program test
real x,y
y = x
print *, y
end
C:\Projects>ifort /Qinit:snan /Qsave t.f90
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 15.0.1.148 Build 20141023
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 12.00.31101.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:t.exe
-subsystem:console
t.obj

C:\Projects>t.exe
forrtl: error (65): floating invalid
Image              PC        Routine            Line        Source
t.exe              0128F359  Unknown               Unknown  Unknown
ntdll.dll          77AC389A  Unknown               Unknown  Unknown
ntdll.dll          77AC3492  Unknown               Unknown  Unknown
ntdll.dll          77ACBC5B  Unknown               Unknown  Unknown
ntdll.dll          77AC01BB  Unknown               Unknown  Unknown
ntdll.dll          77AC01BB  Unknown               Unknown  Unknown
ntdll.dll          77AD0E6B  Unknown               Unknown  Unknown
ntdll.dll          77ABF55E  Unknown               Unknown  Unknown
ntdll.dll          77ABF5EC  Unknown               Unknown  Unknown

C:\Projects>

However, further analysis shows that the error occurs on the print, not the assignment,. Looking at the assembly I see that movss instructions were used to move the data. This doesn't trap on a floating invalid.

0 Kudos
Scott_L_
New Contributor I
829 Views

 

 

main:

 

program checknan

real :: y

call sub(y)

stop

end program checknan

 

in sub.f90:

subroutine sub(y)

real, intent(inout) :: y

real :: x,z

x = y

print *,' set x '

z = y + 1.0

print *,' set z '

return

end subroutine sub

 

 

I set this up quickly and compiled in Debug/x64  with Yes (/Qinit:snan)  and Yes (/Qinit:arrays).

Maybe I did something wrong because it did not trap on either use of y.

 

 

0 Kudos
Steven_L_Intel1
Employee
829 Views

C:\Projects>t.exe
  set x
forrtl: error (182): floating invalid - possible uninitialized real/complex variable.
Image              PC        Routine            Line        Source
t.exe              00BA10EB  _SUB                       22  t.f90
t.exe              00BA1039  _MAIN__                     5  t.f90
t.exe              00BD8092  Unknown               Unknown  Unknown
t.exe              00BD87F5  Unknown               Unknown  Unknown
kernel32.dll       75BF338A  Unknown               Unknown  Unknown
ntdll.dll          77ACBF32  Unknown               Unknown  Unknown
ntdll.dll          77ACBF05  Unknown               Unknown  Unknown

You need to add /Qsave.

0 Kudos
Scott_L_
New Contributor I
829 Views

 

Thanks.  So it is printing "set x" after executing x = y, which must not be generating an exception.   It does generate an exception at z = y+1.0.   So it is when the saved NaN is used in an expression that you see the break.

 

thanks

 

 

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
829 Views

There are two types of NaN: signaling (SNaN) and non-signaling (QNaN) iow Quiet NaN

When a signaling NaN (SNaN) is used in a floating point instruction it will generate an exception. However, if the memory location holding the floating point SNaN is manipulated using general purpose registers (i.e. integer) then an exception will not be generated. A statement like x=y can be executed using general purpose registers (as well as through use of FPU, SSE, AVX floating point instructions). Also note that it is possible for a statement such as IF(X .EQ. Y) to perform an integer bit-wise compare depending on compiler options.

For this reason, you may need to trace back several statement, and/or call levels to find the source of the NaN (most often due to bad programming).

Jim Dempsey

0 Kudos
Reply