- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
-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.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page