I came across a case of Segmentation fault occurring when running a SELECT CASE within a loop a certain number of times.
Similar cases submitted in the past had been sometimes imputed to a buggy implementation of the pthread library, when linked statically to the executable. I have some doubts this one is the same case.
First, a long time has passed since then, and I would hope that the current pthread implementations have been fixed in the meantime (but this is just a hope).
Second, the issue does not occur when using the PGI compiler, which also used the same system pthread library (but perhaps it uses it in a different way).
Third, the error occurs also when the pthread library is linked dinamically, and even when a single thread only is used.
What I can say, after a bunch of tests, is that it seems that the Intel compiler does not clean the stack when exiting from the SELECT CASE construct in a “rude way”, by branching outside of it.
I know that this may not conform to a structured programming style of coding, but: it does not to violate the standard, no warnign is issued at compile time and it works with other compilers (PGI, gfortran).
Below you can find a simple test program. It goes wrong with Intel Fortran Compilers up to Version 18.104.22.168 (and I did not find anything about this issue in the Release notes of the following updates.)
To make the Segmentation fault error show up earlier, simply reduce the stack size (e.g.: ulimit –s 1024)
Note that the issue does not occur if the case-expr is a simple scalar variable, while it occurs when it is an element of an array (and, I guess, whenever it is an expression).
You can see the almost exact proportionality of the number of branches having target outside the constructs with the number of loops performed before blowing out: just replace a number of GOTOs with simple CONTINUEs.
I suspect that a temporary variable is generated in the stack for allocating the result of the case-expr, and it is not freed when exiting the construct by jumping outside, without “politely passing through” the END SELECT statement.
I would be happy if someone could tell me if I’m wrong, and/or if there are specific guidelines (additional to the Standard and the reference manual) about the SELECT CASE construct.
In the meanwhile, seeming the construct unreliable, I had to go back to IF/ELSEIF ladders, with an annoying loss of readability.
integer, parameter :: ws = 32 character(ws), parameter :: wd_0 = 'Word 0 ' character(ws), parameter :: wd_1 = 'Word 1 ' character(ws), parameter :: wd_2 = 'Word 2 ' character(ws), parameter :: wd_3 = 'Word 3 ' character(ws), parameter :: wd_4 = 'Word 4 ' character(ws), parameter :: wd_5 = 'Word 5 ' character(ws), parameter :: wd_6 = 'Word 6 ' character(ws), parameter :: wd_7 = 'Word 7 ' integer, parameter :: nw = 8 character(ws) :: words(0:nw-1) character(ws) :: myword integer :: i, j words = [ wd_0, wd_1, wd_2, wd_3, & wd_4, wd_5, wd_6, wd_7 ] do i = 0, 50000000 j = mod(i,nw) myword = words(j) if ( mod(i,10000) == 0 ) print *, i, j, myword select case(words(j)) case ( wd_0 ) ; go to 100 case ( wd_1 ) ; go to 101 case ( wd_2 ) ; go to 102 case ( wd_3 ) ; go to 103 case ( wd_4 ) ; go to 104 case ( wd_5 ) ; go to 105 case ( wd_6 ) ; go to 106 case ( wd_7 ) ; go to 107 case default ; print *, 'word not found: ', myword end select 100 go to 999 101 go to 999 102 go to 999 103 go to 999 104 go to 999 105 go to 999 106 go to 999 107 go to 999 999 continue end do print *, 'ended' end