Reputation: 105
I have written a fortran code which is failing in a way that I do not understand. I have tried to explain the scenario clearly below but please ask me to clarify if it is not clear.
The code includes a subroutine
SUBROUTINE TMGP(NSYM,NOB,NFT,DEN,ncod,PR,np,lden,NPMX,nuccen,mdel)
IMPLICIT NONE
...
INTEGER :: NINTS
REAL(KIND=wp), ALLOCATABLE :: XBUF(:)
...
print *,"xbuf allocated ?",allocated(xbuf)
print *,"xbuf not allocated ?",.not.allocated(xbuf)
if (allocated(xbuf)) then
DEALLOCATE(xbuf)
end if
if (.not.allocated(xbuf)) then
allocate (xbuf(nints))
end if
...
RETURN
END SUBROUTINE TMGP
However when I run this program it fails on the line:
DEALLOCATE(xbuf)
With the error
forrtl: severe (173): A pointer passed to DEALLOCATE points to an array that cannot be deallocated
With the output:
xbuf allocated ? T
xbuf not allocated ? F
If I change the code to (and make NO other changes than adding this line):
print *,"xbuf allocated ?",allocated(xbuf)
print *,"xbuf not allocated ?",.not.allocated(xbuf)
print *,"nints = ",nints
if (allocated(xbuf)) then
DEALLOCATE(xbuf)
end if
if (.not.allocated(xbuf)) then
allocate (xbuf(nints))
end if
and run this program it fails on the line:
allocate (xbuf(nints))
and I get the message:
forrtl: severe (151): allocatable array is already allocated
With the output:
xbuf allocated ? F
xbuf not allocated ? T
nints = 1
I am quite baffled by this as it seems to me the if statements I have used should make this kind of issue impossible and following the logic of the code these errors should not be possible.
I am using ifort compiler, any ideas on what could be causing this issue or suggestions on how to fix it would be very much appreciated.
Please let me know if any additional information would be useful.
James
Upvotes: 1
Views: 2177
Reputation: 21431
Your observations are a likely consequence of corruption of the internal descriptor that the compiler uses to track the status of an allocatable (or pointer) object, interacting with the way in which that specific compiler stores and tests the allocation status of an object.
This is very much implementation detail for that specific compiler, but there are at least two ways in which the "allocated" status of an object is stored in the descriptor for the object - a non-null machine address for the actual data backing the object, and a separate flag set in the descriptor. The allocated intrinsic is looking at one of these pieces of information, while the runtime support for the ALLOCATE statement is looking at another. Normally these two pieces of information are consistent, but in the face of memory corruption you see the apparent contradiction. Documentation for the layout of the descriptor for the current version of Intel Fortran can be found at https://software.intel.com/en-us/node/525356.
(Another flag tracks whether the descriptor is for something that can be deallocated (i.e. it was something created by ALLOCATE or similar) or not (perhaps the descriptor is for a pointer that references a section of another array) - corruption of that flag results in the "... array cannot be deallocated" message.)
The memory corruption is likely caused by an error in your program, which may not be in the immediate source location of the array declaration and use. As suggested by others in the comments - go looking for programming errors in your code such as array subscripts being out of bounds or mismatches in argument lists. The compiler's runtime diagnostic options often help. With appropriate debugging ability, you can also monitor the memory storage for the relevant array descriptor, and determine exactly when the inconsistency in the state of the descriptor first appears.
Upvotes: 3