- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We have a lot of Fortran code, which compiled and run fine under Intel Fortran 12.1 (Windows). However, under version 16.0, we find some runtime errors around arrays having been already allocated.
Intel's help and the Fortran standard say that these deallocate statements should not be necessary:
If a RETURN or END statement terminates a procedure, an allocatable array has one of the following allocation statuses:
- It keeps its previous allocation and association status if the following is true:
- It has the SAVE attribute.
- It is in the scoping unit of a module that is accessed by another scoping unit which is currently executing.
- It is accessible by host association.
- It remains allocated if it is accessed by use association.
Otherwise, its allocation status is deallocated.
As best I can tell none of the above allocation statuses are true, meaning the code should fall back to the Otherwise clause. In other words this code should not be failing.
Has there been any sort of change made? Is there any reason in the code below why the arrays allocated need to be deallocated?
(We have a large number of commercial paid Fortran licenses, so I could also log this with support if need be?)
----
!DEC$ ATTRIBUTES STDCALL :: c_checkcanstillrunwithdata INTERFACE subroutine c_checkcanstillrunwithdata + ( + nItems_,daArray_,iSect_,nParams_,nSect_,iSSect_, + iaDim_,iaUnit_,iStatus_ + ) INTEGER nItems_,iSect_,nParams_,nSect_,iStatus_ integer iaDim_(nItems_),iaUnit_(nItems_),iSSect_ double precision daArray_(nItems_) !DEC$ ATTRIBUTES VALUE :: nItems_ !DEC$ ATTRIBUTES REFERENCE :: daArray_ !DEC$ ATTRIBUTES VALUE :: iSect_ !DEC$ ATTRIBUTES VALUE :: nParams_ !DEC$ ATTRIBUTES VALUE :: nSect_ !DEC$ ATTRIBUTES VALUE :: iSSect_ !DEC$ ATTRIBUTES REFERENCE :: iaDim_ !DEC$ ATTRIBUTES REFERENCE :: iaUnit_ !DEC$ ATTRIBUTES REFERENCE :: iStatus_ END subroutine c_checkcanstillrunwithdata END INTERFACE !DEC$ ATTRIBUTES STDCALL :: c_checkcanstillrun INTERFACE subroutine c_checkcanstillrun + ( + iStatus__ + ) INTEGER iStatus__ !DEC$ ATTRIBUTES REFERENCE :: iStatus__ END subroutine c_checkcanstillrun END INTERFACE integer iSect,krs_FindSection,nParam,krs_GetNumParam_U,nSect, + i,ipt,nRet,ip,iplist,iaa,pdimc,attrib,ndi,nExpected, + nosubs logical madeCall,bSet integer, allocatable :: iaDim(:),iaUnit(:) include 'switch_keys.inc' include 'indexs.com' include 'sys_mindexsizes.inc' include 'dimension_keys.inc' ! ! ----------------------------------------------------------------------------- ! find StatusMonitor section in current model iSect = krs_FindSection('STATUSMONITORS') madeCall = .false. if(iSect.gt.0) then nParam = krs_GetNumParam_U(iSect) nSect = nosubs(iSect,1) if(iSSect.eq.0) then nExpected = nParam*nSect else nExpected = nParam endif if(nExpected.eq.nItems) then !set up return structure to hold data items, copying approach in krs_GetResults !we do not need to post the values though, just pass through allocate(iaDim(nParam)) allocate(iaUnit(nParam)) !fill in structure, looking up dimension codes as we go !code assumes each parameter has one argument only i = mindex(psclst+2*iSect) + moffst ipt = mindex(i+3) nRet = 0 do ip = 1, nParam iplist = ipt + moffst !parameter entry ipt = mindex(iplist) !next in list iaa = mindex(iplist+4) + moffst !argument entry pdimc = DKNULL if(mindex(iaa+2).gt.0) then attrib = mindex(iaa+2) + moffst if(mindex(iaa+1).eq.fixldf.or.mindex(iaa+1).eq.3) then !get dimension call krs_gattrc (attrib,SWDIM,ndi,pdimc,bSet) endif endif iaDim(ip) = pdimc iaUnit(ip) = 1 end do call c_checkcanstillrunwithdata (nItems,daArray, + iSect,nParam,nSect,iSSect, + iaDim,iaUnit,iStatus) madeCall = .true. endif endif if (.not.madeCall) then !error in setup: fallback to basic method sans data call c_checkcanstillrun(iStatus) endif end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Do you by any chance /Qsave in effect now? https://software.intel.com/en-us/node/579563
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The include files are not provided, and some lines of code have statements starting before column 7. Please provide compilable code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Do you by any chance /Qsave in effect now? https://software.intel.com/en-us/node/579563
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We do use Qsave, how does that impact allocatable arrays as in the way they are declared here?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
benifkc wrote:
We do use Qsave, how does that impact allocatable arrays as in the way they are declared here?
module m implicit none contains subroutine sub() integer, allocatable :: iarr(:) integer :: istat character(len=80) :: erralloc allocate( iarr(2), source=[ 1, 2 ], stat=istat, errmsg=erralloc) if (istat == 0) then print *, " iarr = ", iarr else print *, " allocation failed. istat = ", istat, " errmsg = ", erralloc end if return end subroutine sub end module m
program p use m, only : sub implicit none integer :: i do i = 1, 2 call sub() end do stop end program p
Compiled with /Qsave and run:
iarr = 1 2 allocation failed. istat = 151 errmsg = allocatable array is already allocated Press any key to continue . . .
Compiled with default or /Qauto and run:
iarr = 1 2 iarr = 1 2 Press any key to continue . . .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To see the effect of /Qsave, you can run the following program twice, once without and again with /Qsave
program allocs implicit none integer i do i=1,3 call sub(i) end do contains subroutine sub(k) integer, intent(in) :: k integer, allocatable :: x(:) write(*,*)'Entered sub with k = ',k if(allocated(x))then write(*,*)'x is allocated, size = ',size(x) deallocate(x) else write(*,*)'x is not allocated' endif allocate(x(k)) write(*,*)'(Re)allocated x with size ',size(x) return end subroutine end program
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hmm, it is beginning to look like one of those "why did this ever work" type situations? Well we only have 273 files where Fortran arrays are dynamically deallocated, so we can review them and clean this up. (That is a tiny fraction of our code, trust me, 273 is nothing)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
benifkc wrote:
... trust me, 273 is nothing)
Precisely, since 273 K = -0.15 °C, which can be rounded to "nothing"!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Allocate is called in 280 Fortran files, but deallocate is only called in 207 files. So the cleanup might not be that bad. Hahahaha. You gotta laugh when you can.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page