- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page