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

Array-valued function segmentation error

Roger_D_
Beginner
852 Views

The code below fails with segmentation error unless the arrays "f" and "e" have the same dimension using the Intel Fortran compiler. Appreciate if someone can explain why the array "f" cannot be larger (and much larger) than the array "e." Gfortran does not fail.

---

program test_arrfunc1

! Test of array-valued functions, Aug. 12, 2014.
! Red Hat Enterprise Linux Workstation release 6.5 (Santiago)
! $ ifort --version
! ifort (IFORT) 14.0.1 20131008
! Copyright (C) 1985-2013 Intel Corporation.  All rights reserved.
! $ ifort -traceback test_arrfunc1.f90
! $ ./a.out
! forrtl: severe (174): SIGSEGV, segmentation fault occurred
! Image              PC                Routine            Line        Source             
! a.out              000000000046E269  Unknown               Unknown  Unknown
! a.out              000000000046CBE0  Unknown               Unknown  Unknown
! a.out              000000000043E872  Unknown               Unknown  Unknown
! a.out              0000000000423363  Unknown               Unknown  Unknown
! a.out              0000000000402FCB  Unknown               Unknown  Unknown
! libpthread.so.0    0000003E9440F710  Unknown               Unknown  Unknown
! a.out              0000000000476286  Unknown               Unknown  Unknown
! a.out              0000000000402CCA  MAIN__                     46  test_arrfunc1.f90
! a.out              0000000000402BA6  Unknown               Unknown  Unknown
! libc.so.6          0000003E9401ED1D  Unknown               Unknown  Unknown
! a.out              0000000000402A99  Unknown               Unknown  Unknown
!
! Works when "real(kind=dp),dimension(np) :: f" is defined. Output is here:
! $ ./a.out
! f   1.00000000000000        2.00000000000000        3.00000000000000     
!    4.00000000000000        5.00000000000000        6.00000000000000     
!    7.00000000000000        8.00000000000000        9.00000000000000     
!    10.0000000000000     

  implicit none

  integer,parameter :: i4b = selected_int_kind(9)
  integer,parameter :: dp = kind(0.0d0)

  integer(kind=i4b) :: i
  integer(kind=i4b),parameter :: np = 10

  real(kind=dp),dimension(np) :: e
!  real(kind=dp),dimension(np) :: f     ! works
  real(kind=dp),dimension(10000) :: f   ! fails

  e = (/(i, i=1,np)/)   ! generate some values

  ! call array-valued function
  f = arrfunc1(e,np)
  print *,'f',f(1:np)
        
  contains
    function arrfunc1(e,np)
    implicit none

    integer,parameter :: i4b = selected_int_kind(9)
    integer,parameter :: dp = kind(0.0d0)

    integer(kind=i4b),intent(in) :: np
    real(kind=dp),dimension(np),intent(in) :: e
    real(kind=dp),dimension(np) :: arrfunc1

    arrfunc1 = e
    end function arrfunc1

end program test_arrfunc1
---

Thanks!

 

 

0 Kudos
10 Replies
Steven_L_Intel1
Employee
852 Views

Because your program is not legal Fortran. Unless f is an allocatable array, the language requires that the shapes of f and e match. They don't, so the results are unpredictable. It might corrupt memory, might access unavailable memory (segfault), or might run without errors. All of these are acceptable by the standard.

If f is an allocatable, deferred-shape array and you compile with -standard-semantics, it will work in Intel Fortran.

0 Kudos
Roger_D_
Beginner
852 Views

Steve,

OK. I tried making "f" a deferred shape array and allocated 10000 elements ...

 integer(kind=i4b),parameter :: np = 10

 real(kind=dp),dimension(np) :: e
 real(kind=dp),dimension(:),allocatable :: f   ! works

 e = (/(i, i=1,np)/)   ! generate some values

  allocate(f(10000))
  ! call array-valued function
  f = arrfunc1(e,np)
  print *,'f',f(1:np)
  deallocate(f)

...

It works only if I compile with -standard-semantics as you pointed out. However, coming from old fortran and not an expert on modern fortran this is is indeed confusing, and I did not know this compiler option existed.

I checked all here:

https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors/

and was unable to understand the root cause. So I thank you very much indeed! If you have any other links useful in this context, please advice.

Thanks,

Roger

 

0 Kudos
Steven_L_Intel1
Employee
852 Views

You could have skipped the ALLOCATE if you used -standard-semantics.

In the case where f is not allocatable, the shapes (dimensions and extents of each dimension) must conform. The compiler needs to decide how many elements to transfer, and it might take that from the left side or from the right. If it decides to take it from the left, 10000 elements, you'll likely run off the end of allocated memory and get the segfault. There are many, many ways to get a segfault and it's not possible to write an article listing each and every one.

Prior to Fortran 2003, even allocatable arrays followed this rule. But F2003 added the behavior that if an allocatable array was on the left of an assignment, if necessary it was (re)allocated automatically to match the shape of what was assigned to it. We felt that the extra code needed to do this check would unfairly penalize programs that had done explicit allocations, so we did not make the reallocation default. We are discussing changing this behavior in the future, however. -standard-semantics is shorthand for all the options that change default behaviors that aren't F2003 compliant.

0 Kudos
Roger_D_
Beginner
852 Views

I have a much better understanding now ... thanks again. Just a few comments/questions.

1) Checked the code and it was confirmed that with the allocate statement in place and compiled with -standard-semantics the array "f" is being reallocated (from 10000 to 10 elements).

2) I removed the allocate statement and it works fine too (when compiled with -standard-semantics). As long as "f" is allocatable the shape (extent) will be the same as the shape from the array function.

3) Question: Is it important to use the deallocate statement? I have read that it is no longer necessary and memory is released when the function or subroutine exits.

PS. The code above is of course just a modified snippet of a much larger code (3000 lines in Fortran 77) which I was working on to include a few new procedures. It failed (with segmentation error) due to the issue discussed here. I was also unable to use the debugger (idb). It did not step properly in the called function. It stepped into the routine but then jumped several lines and values did not make sense.

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
852 Views

Steve,

I know that standards committees are loath to adding new keywords, but I as a user am loath to having behavioral changes in existing code. I think this is a case where there should have been a new keyword introduced:

real, allocatable :: A(:) ! not reallocatable

real, reallocatable :: B(:) ! allocatable and reallocatable

Being an attribute, would likely present no conflict with code.

Jim Dempsey

 

0 Kudos
Steven_L_Intel1
Employee
852 Views

Local ALLOCATABLE variables that don't have the SAVE attribute are automatically deallocated when they go out of scope. It's good practice to deallocate them explicitly anyway.

Jim, I'm not in favor of a separate keyword - it just complicates things. My personal opinion is that the overhead of checking is low - perhaps we could have an option to turn it off if deemed necessary. I know the compiler team is very sensitive to anything that affects performance in a negative way, but I feel we need to weigh this against the increasingly frequent surprise of users when Intel Fortran doesn't work the way the standard says it should. Maybe 10+ years ago, when we added this feature, the decision was appropriate, but not now.

0 Kudos
Roger_D_
Beginner
852 Views

Steve and Jim,

Thanks to you both! It's good to know that the Intel compiler works fine. I suspected a compiler issue and since I haven't done much modern Fortran programming your comments are insightful to how the Intel compiler works for this issue. And it's good to know that this Forum is active with good support (first time post).

 

0 Kudos
FortranFan
Honored Contributor III
852 Views

Steve Lionel (Intel) wrote:

Local ALLOCATABLE variables that don't have the SAVE attribute are automatically deallocated when they go out of scope. It's good practice to deallocate them explicitly anyway.

...

With automatic deallocation or with an explicit deallocation statement, another point to consider is when the compiler actually releases the memory.   Steve, can you please comment on what one can expect with Intel Fortran?

Steve Lionel (Intel) wrote:

..

Jim, I'm not in favor of a separate keyword - it just complicates things. My personal opinion is that the overhead of checking is low - perhaps we could have an option to turn it off if deemed necessary. I know the compiler team is very sensitive to anything that affects performance in a negative way, but I feel we need to weigh this against the increasingly frequent surprise of users when Intel Fortran doesn't work the way the standard says it should. Maybe 10+ years ago, when we added this feature, the decision was appropriate, but not now.

I agree with Steve - the chances of a new "REALLOCATABLE" keyword adding to the confusion are indeed high.

But Steve, re: your statement, "the increasingly frequent surprise of users when Intel Fortran doesn't work the way the standard says it should", I wonder if it is now time for -standard-semantics to be the default option.  What are your and the Intel compiler team's views on this?

0 Kudos
TimP
Honored Contributor III
852 Views

It may be interesting to know if Steve can confirm that performance deficits in -standard-semantics have been improved upon for the next release.  I suppose I'm in a minority in not using the option because in the past it prevented optimization of MAXLOC/MINLOC.   The performance of -assume minus0 (which is needed to conform with f95 and later) has been excellent for several releases.

0 Kudos
Steven_L_Intel1
Employee
852 Views

-standard-semantics has a LOT of effects. We did look at this and realized that we could never make it the default as it would change the meaning of such things as RECL= in an OPEN. But we could make the automatic reallocation default, and we've been doing some testing about that, both for performance and looking for bugs. It might happen for next year's release.

Another option we've considered making default is -heap-arrays.

FortranFan, when an allocatable variable is deallocated, we call "free". What happens after that is out of our control.

0 Kudos
Reply