Very strange FORTRAN bug with comparing integers
I'm trying to check how many times certain lines are executed in few timesteps, here is part of my code: 1)write "countd" every time:
real(kind=8) function dergfm(jp,ip,lp)
integer :: jp,ip,lp,countd
real(kind=8) press
.
.
.
countd=countd+1
!if (countd < 5) then
print*, "countd= ", countd
!endif
.
.
.
end function dergfm
result:
countd= 1
.
.
.
countd= 21504
2)write "countd" first 4 times:
real(kind=8) function dergfm(jp,ip,lp)
integer :: jp,ip,lp,countd
real(kind=8) press
.
.
.
countd=countd+1
if (countd < 5) then
print*, "countd= ", countd
endif
.
.
.
end function dergfm
results:
countd= 1
countd= 2
countd= 3
countd= 4
3)write "countd" larger than 5
real(kind=8) function dergfm(jp,ip,lp)
开发者_如何学运维integer :: jp,ip,lp,countd
real(kind=8) press
.
.
.
countd=countd+1
if (countd > 5) then
print*, "countd= ", countd
endif
.
.
.
end function dergfm
results:
[none]
It looks like comparing these integers works for .lt. but doesn't for .gt. (nor .eq.)
countd is a local variable to a function. As such, its value it not necessarily retained between calls, unless you add the "save" attribute to the declaration. Try this and see if the code starts behaving. And how do you initialize countd? I would use the following:
integer, save :: countd = 0
In this case the "save" is optional because it is implied by the initialization in the declaration.
If the variable was not SAVE'd, the behavior is undefined and strange things can happen. For some compilers, the value of COUNTD will be initialized to zero and the code will work as expected. For other compilers, you will get complete garbage every time you call this subroutine.
Other times (which I suspect is your case), the variable is put on the stack and MAY get assigned the same memory each time the subroutine is called. Or, it may get assigned the same memory the first 4 or 5 times, then some other subroutine corrupts the stack on the 6th time and the value of COUNTD becomes garbage.
The correct answer is to SAVE the variable and initialize it with a data statement. This is portable and will work on every system.
精彩评论