とあるプログラムのデバッグをしていたときのこと。浮動小数点例外が起きてエラーで止まってしまいました。当初はゼロ割を疑っていたのですが、printデバッグしてみたところ、どうも違うらしく、じゃあ原因はなんだろうといろいろ試していたところ、コードに仕込んだprint文が標準出力されないことに気づき、バグの原因が判明しました。結論から言うと、cycle x_loop と書くべきところが exit x_loop になっており、まるっとループを抜ける仕様になっていました。違いを以下のサンプルコードで見てみましょう。
program main
implicit none
integer(4), parameter :: ixmax = 5
integer(4), parameter :: ix_exit = 2
real(4), parameter :: undef_s = huge(0.0e0)
integer(4) :: ix1, ix2
real(4) :: rx1(ixmax), rx2(ixmax)
print*, "start x_loop1"
x_loop1: do ix1 = 1, ixmax
print*, 'ix1 = ', ix1
rx1(ix1) = real(ix1)
if ( ix1 == ix_exit ) then
rx1(ix1) = undef_s
print*, "exit x_loop1"
exit x_loop1
end if
end do x_loop1
print*, "start x_loop2"
x_loop2: do ix2 = 1, ixmax
print*, 'ix2 = ', ix2
rx2(ix2) = real(ix2)
if ( ix2 == ix_exit ) then
rx2(ix2) = undef_s
print*, "cycle x_loop2"
cycle x_loop2
end if
end do x_loop2
print*, "rx1 = ", rx1
print*, "rx2 = ", rx2
end program main
これを実行すると私の環境では以下のようになりました。意図しているのは後者のほうですが、前者では途中でループを抜けてしまっているので、実数配列の後半が不定になってしまっており、特に4番目の要素には意図しない値が混入してしまっています。
$ ./a.out
start x_loop1
ix1 = 1
ix1 = 2
exit x_loop1
start x_loop2
ix2 = 1
ix2 = 2
cycle x_loop2
ix2 = 3
ix2 = 4
ix2 = 5
rx1 = 1.00000000 3.40282347E+38 0.00000000 -2.35710200E+21 0.00000000
rx2 = 1.00000000 3.40282347E+38 3.00000000 4.00000000 5.00000000
exit なのか cycle なのかは、どういうプログラムにするかに依るので、よくよく考えて使い分けましょう。