I've spent the last two days debugging a seemingly nonsensical segfault in a large Fortran project. The problem started when I moved the code to my own computer, and the segfault arised in a part of the code that has been working fine for years on several other systems. I eventually found the source of the segfault, but it is so astonishingly unexpected (and compiler-dependent) that I decided to post it here.
Consider the following MWE:
program dafuq
implicit none
integer :: a=1
integer, parameter :: b=2
call foo(a,b)
end program dafuq
subroutine foo(a,b)
implicit none
integer, intent(inout) :: a, b
a=b !OK
b=a !causes segfault
end subroutine foo
I have access to two HPC clusters, which together with my laptop allows me to check these (occasionally somewhat old) compilers:
- ifort 11.1
- gfortran 4.1.2
- gfortran 4.4.7
- gfortran 4.8.4 (the newest in the repos for Ubuntu 14.04)
It turns out that all four compilers produce a segfault with the above code, because variable b is declared as a parameter. Consequently it's a violation to change its value in the subroutine. My problem is that only the newest gfortran shows a warning during compile (even with -Wall), and that too goes away if I omit the intent specification in the subroutine. I suspect that the same setup in C++ using const variables would raise a huge red flag.
Now, to make it more obscure, consider the following code, with arrays instead of scalars:
program dafuq_array
implicit none
integer :: a(2)=(/1,1/)
integer, parameter :: b(2)=(/2,2/)
call foo(a,b)
end program dafuq_array
subroutine foo(a,b)
implicit none
integer, intent(inout) :: a(2), b(2)
a=b !OK
b=a !might cause segfault
end subroutine foo
Now, in THIS case, the newest gfortran produces a segfault, while the other three compilers don't! (Actually this is the reason why I didn't encounter this problem earlier: the newest gfortran on the list is the one on my own computer.) In all cases I used essentially no compile switches, i.e. ifort -o mwe mwe.f and the same for gfortran.
Even though I found the reason for the segfault and I sort of understand it, there are still a few things which bug me (no pun intended).
- Am I wrong for expecting a compile error/warning in such cases? Or at least a run-time error beyond "invalid memory reference".
- Does it make sense that using arrays avoids this error for some compilers?
- Am I right that the different behaviour encountered on different systems is due to the difference in compilers, or could it be more subtly system-specific?