Stack Overflows in Fortran

March 13, 2010

Consider the following program, which allocates two rather large integer arrays and performs a simple operation with them (addition). The call to the foo subroutine involves two automatic arrays of dimension n.

program segfault1
  implicit none
  call foo(4096000)
contains
  subroutine foo(n)
    integer, intent(in) :: n
    integer, dimension(n) :: a, b
    a = 1
    b = 2
    a = a + b
    print *, sum(a)
  end subroutine foo
end program segfault1

Depending on how your compiler handles the automatic arrays—whether they are allocated on the heap or the stack—this program may cause a segmentation fault. For example, when compiled with a recent version of the Intel Fortran compiler, the above program segfaults:

% ifort segfault1.f90 && ./a.out
zsh: segmentation fault  ./a.out

The program runs fine when compiled with GNU Fortran. The difference is explained by the behavior of these two compilers with respect to allocating automatic arrays. Intel Fortran allocates automatic arrays on the stack by default while GNU Fortran allocates them on the heap.

% gfortran segfault1.f90 && ./a.out
    12288000

There are several solutions. First, the code can be redesigned using work arrays or other similar methods. I won’t cover that case here. Another solution involving changes to the code is to explicitly allocate large arrays:

program segfault2
  implicit none
  call foo(4096000)
contains
  subroutine foo(n)
    integer, intent(in) :: n
    integer, dimension(:), allocatable :: a, b
    allocate(a(n), b(n))
    a = 1
    b = 2
    a = a + b
    print *, sum(a)
    deallocate(a, b)
  end subroutine foo
end program segfault2
% ifort segfault2.f90 && ./a.out
    12288000

A platform-specific solution, on Unix-based systems, is to increase the stack limit using the shell:

% ulimit -s unlimited
% ifort segfault1.f90 && ./a.out
    12288000

A final, compiler-specific solution is to use your compiler’s command-line options to change the default behavior to allocate temporary arrays on the heap instead of the stack. For example, the Intel Fortran compiler provides the following option:

-heap-arrays [n]
    temporary arrays of minimum size n (in kilobytes) are allowed in
    heap memory rather than on the stack

With this option, the program works as expected:

% ifort -heap-arrays 1024 segfault1.f90 && ./a.out
    12288000