Title: Notes on a Fortran Conversion, part 2 Date: 06/10/2020 Category: Programming
I found this a fascinating example of the following programmer’s mantra:
“It can’t possibly not work!” “I found it why it doesn’t work” “How did that ever work?”
subroutine set_fast(flag)
real(kind=8) :: xmeas, xmv
common /pv/ xmeas(42), xmv(12)
real(kind=8), intent(in) :: time
character(len=20), intent(in) :: flag
logical :: init = .false.
integer :: i
character(len=10) :: tmp, mode = ""
select case(flag)
case ("--xmv") ! program
if (.not. init) then
call get_command_argument(2, tmp)
read(tmp, *) i
call get_command_argument(3, tmp)
read(tmp, *) mode
end if
select case (mode)
case ("MAX")
xmv(i) = 100.
! omitted for brevity
end select
end select
init = .true.
end subroutine
I wanted to add another case, as you do:
case ("--xmeas") ! program
if (.not. init) then
call get_command_argument(2, tmp)
read(tmp, *) i
call get_command_argument(3, tmp)
read(tmp, *) mode
end if
select case (mode)
case ("MAX")
xmeas(i) = 200.
case ("MIN")
xmeas(i) = -10.
end select ! xmeas variations
And… segfault. Oh dear. Worse, only on a release build - debug handles this just fine.
Did you see it? If not - spoilers ahead - it’s the index value, which is only read the first time. Shamefully, I only resolved this with print statements.
Somehow, without the second case, i retained the correct value. With the second case, even if never invoked, i ended up as LARGE_INT on subsequent runs.
Adding integer:: i = 0
tells the compiler to retain the value for future invocations.