Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29236 Discussions

Has anyone had stack overflows on Linux in spite of using -heap-arrays 0?

Mark_Lewy
Valued Contributor I
535 Views

I've had at least 3 different instances of code that are creating stack temporary variables in spite of the source file being compiled with -heap arrays 0 on Linux, so may seg fault with sufficiently large arrays.  The same code runs fine on Windows.

I've created a reproducer for one in service request 06435812, but before I try to create reproducers for the others, has anybody had similar issues?

In 06435812, the idiom is

 

    pure subroutine do_something(this)
        class(c), intent(inout) :: this
        ! integer, parameter :: dp = kind(0.0d9)
        ! class c contains real(dp), allocatable, dimension(:) components arr1 & arr2
        ! It is assumed that size(this%arr1) == size(this%arr2)

        real(dp) :: local(size(this%arr1))

        local = this%arr1 + this%arr2 ! Potential seg fault here

        ! Elided
    end subroutine

 

I've found this crashes in IFX 2024.0 and later (including 2025.0)

The 2nd case looks like

 

    module subroutine do_something(defn)
        integer, intent(in) :: defn

        ! array is an allocatable array of a user-defined type, say t
        ! results and gauges are integer arrays to be used as vector subscripts
        ! size(gauges) >= n_gauges
        ! get_max_val and get_val are elemental functions returning double precision values (type bound procedures)
        ! spr_write_value is an interface - the specific match for this case takes an argument val declared as real(kind(0.0d0)), intent(in) :: val(:)

        select case (defn)
        case (def_summary)
            call spr_write_value(array(results)%get_max_val())
        case (def_results)
            call spr_write_value(array(results)%get_val())
        case default
            ! May seg fault here
            associate (g => array(gauges(1: n_gauges)))
                call spr_write_value(g%get_val())
            end associate
        end select
    end subroutine

 

In this case it appears that a temporary is being created for the ASSOCIATE name.  The workaround was to make size(gauges) == n_gauges  by shrinking gauges to fit and passing array(gauges)%get_val() to spr_write_value rather than using an ASSOCIATE block.  Found in IFX 2024.0.

And the third case:

 

    subroutine do_something
        ! Subcatchments is allocatable array of type subcatchment_t
        ! result_subcatchments is an allocatable integer array of size nresult_subcatchments
        ! nresult_subcatchments <= size(Subcatchments)
        ! spr_write_value is an interface, in this case it resolves to a
        ! specific procedure with argument val declared as character(*), intent(in) :: val(:)
        ! integer, parameter :: subcatchid_len = 64
        ! get_id_adjustr is a type bound elemental function returning a character(subcatchid_len)

        integer :: i, ios

        ! Elided
#ifdef linux
        character(subcatchid_len), allocatable :: tmp_ids(:)
#endif

        ! Elided

#ifdef linux
        ! Linux versions of the Intel Fortran compiler (IFORT and IFX, up to 2023.2, at least)
        ! create a stack temporary for Subcatchments(result_subcatchments)%get_id_adjustr()
        ! when it's used as an argument to spr_write_value - this may cause failures due to stack overflow.
        ! Explicitly create a temporary heap array to avoid this.
        allocate(tmp_ids(nresult_subcatchments), stat = ios)
        call check_allocate_status(ios)

        do i = 1, nresult_subcatchments
            tmp_ids(i) = Subcatchments(result_subcatchments(i))%get_id_adjustr()
        end do
        call spr_write_value(tmp_ids)
#else
        call spr_write_value(Subcatchments(result_subcatchments)%get_id_adjustr())
#endif

         ! Elided
end subroutine

 

You can see the workaround here was to create a temporary heap variable on Linux.

These are all buried deep in a large commercial program, so before I attempt to create reproducers for the 2nd and 3rd cases has anyone reported anything similar?

It is also possible that these latter cases have been fixed in later versions. If so, there is no point in me creating reproducers either.

0 Kudos
1 Solution
Mark_Lewy
Valued Contributor I
353 Views

I'm assuming nobody else has had the same issue, but I found the solution was to use "-heap arrays" instead of "-heap arrays 0" on Linux.  I used "-heap arrays 0" originally because it looked equivalent to "/heap-arrays:0" on Windows.  Apparently not!

View solution in original post

0 Kudos
1 Reply
Mark_Lewy
Valued Contributor I
354 Views

I'm assuming nobody else has had the same issue, but I found the solution was to use "-heap arrays" instead of "-heap arrays 0" on Linux.  I used "-heap arrays 0" originally because it looked equivalent to "/heap-arrays:0" on Windows.  Apparently not!

0 Kudos
Reply