コンパイルの最適化オプションによって結果に違いが出る場合があります。
Fortranにおいて、わかりにくいバグが発生したので、備忘録的にこちらに書いておきます。
突然ですが、以下のFortranコードを見てください。
test.f90
module testmodule
type testtype
contains
procedure::test
end type testtype
contains
subroutine test(self,i,v)
implicit none
class(testtype)::self
integer,intent(in)::i
complex(8),intent(out)::v
write(*,*) "1",v*i
end subroutine
end module testmodule
program main
use testmodule
implicit none
complex(8)::v
integer::i
type(testtype)::t1
i = 10
v = 1d0
call t1%test(i,v)
i = 10
v = 1d0
call test2(i,v)
!write(*,*) v
contains
end program main
subroutine test2(i,v)
implicit none
integer,intent(in)::i
complex(8),intent(out)::v
write(*,*) "2",v*i
end subroutine
このコード、gfortranでのコンパイルの最適化レベルのオプションの違いによって、異なる結果を返します。
gfortran test.f90
だと、
1 (10.000000000000000,0.0000000000000000)
2 (10.000000000000000,0.0000000000000000)
gfortran test.f90 -O2
だと、
1 (0.0000000000000000,0.0000000000000000)
2 (10.000000000000000,0.0000000000000000)
となります。
実は、このコードは作成者としては10が出て欲しいコードです。
しかし、一箇所バグが混入しているため、最適化レベルによって結果が変わってしまっています。
バグはどこでしょうか?
答えは、
complex(8),intent(out)::v
は
complex(8),intent(in)::v
とすべきです。inとoutを間違って入力してしまった、ということです。
outなので本来は値が入力されないにも関わらず、直前でのvの値が入ってしまっていて、結果的にintent(inout)のような挙動をしています。オブジェクト指向で書いた場合にO2とした時は、それをちゃんと反映したのか、きちんとvの値が反映されず、10とは表示されません。