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

Deallocation of pointer to slice identical to "whole" fails

tjahns
Beginner
548 Views

The following test program exhibits what I think is not clearly allowed for forbidden by the standard but works on any compiler but the Intel versions I tried (14.0.2, 15.0.0):

PROGRAM ifort_ptr_dealloc
  REAL, POINTER :: p(:, :, :), q(:, :)
  ALLOCATE(p(5,6,1))
  p = 1.0
  q => p(:, :, 1)
  DEALLOCATE(q)
END PROGRAM ifort_ptr_dealloc

Compiling and running results in an abort:

$ ifort -o ifort-ptr-dealloc ifort-ptr-dealloc.f90
$ ../ifort-ptr-dealloc 
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image              PC                Routine            Line        Source             
ifort-ptr-dealloc  00000000004081B2  Unknown               Unknown  Unknown
ifort-ptr-dealloc  0000000000402E95  Unknown               Unknown  Unknown
ifort-ptr-dealloc  0000000000402CAE  Unknown               Unknown  Unknown
libc.so.6          00007F9C579F2CAD  Unknown               Unknown  Unknown
ifort-ptr-dealloc  0000000000402BB9  Unknown               Unknown  Unknown

Since most other compilers tried (pgfortran 14.7, nagfor 5.3.2(990), gfortran 4.8.2) happen to work I hope this can be resolved. Except for xlf 13.1.0.8 and 14.1.0.8, where AIX 6.1 running on POWER6 was used and the program was also aborted, all tests were made on Intel Xeon E5-2665 CPU running 64bit Linux.

Regards, Thomas

0 Kudos
10 Replies
Kevin_D_Intel
Employee
548 Views

I submitted a (Low) enhancement request to Development (see internal tracking id below) for consideration and will update the thread with details of what I hear regarding it.

(Internal tracking id: DPD200239656)

0 Kudos
jimdempseyatthecove
Honored Contributor III
548 Views

>>Since most other compilers tried (pgfortran 14.7, nagfor 5.3.2(990), gfortran 4.8.2) happen to work I hope this can be resolved.

???

I think you mean happen to fail to report an error.

P was allocated, Q was not.

Consider:

PROGRAM ifort_ptr_dealloc
  REAL, POINTER :: p(:, :, :), q(:, :)
  ALLOCATE(p(5,6,7)) ! *** NOTE 7
  p = 1.0
  q => p(:, :, 1) ! A slice of P not whole of P
  DEALLOCATE(q)
END PROGRAM ifort_ptr_dealloc

What do you expect to happen? From your statement regarding (pgfortran 14.7, nagfor 5.3.2(990), gfortran 4.8.2) I suppose you would expect only the slice of P to be deallocated.

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
548 Views

It may be that the standard permits the "slice identical to whole" to be deletable.

I do not know the internals of Fortran to know if internally the allocations internally have a reference count, and/or a list of references.

If so, then in the original example, the deallocate(q) would also have to disassociate p (and all other pointers). This could be implemented by use of an allocation object, containing something like a void* and a reference count. And the pointers containing an array descriptor and a reference to the allocation object.

Jim Dempsey

0 Kudos
Harald
Beginner
548 Views

It appears that the pointer q is associated with a rank-2 slice of the rank-3 array p, so while the extent of the third dimension of p happens to be 1, I don't think that q can be considered equivalent to the whole of p.

If you add a statement

  print *, associated (p)

after the deallocate statement, you'll see that gfortran and NAG print a "T", which I think is fine.

If I compile with "ifort -check all -g ifort_ptr_dealloc.f90 -traceback", I get:

forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image              PC        Routine            Line        Source             
a.out              08059984  Unknown               Unknown  Unknown
a.out              0804A66A  MAIN__                      6  ifort_ptr_dealloc.f90
a.out              08049FD6  Unknown               Unknown  Unknown

which I think is also fine, as the deallocate invokes undefined behaviour, as you already mentioned.

 

0 Kudos
Steven_L_Intel1
Employee
548 Views

If the slice is the whole array, the standard says you should be able to deallocate it. I thought I reported this some time ago but can't find the issue right now, so it's good that Kevin did so,

0 Kudos
tjahns
Beginner
548 Views

Harald wrote:

It appears that the pointer q is associated with a rank-2 slice of the rank-3 array p, so while the extent of the third dimension of p happens to be 1, I don't think that q can be considered equivalent to the whole of p.

If you add a statement

  print *, associated (p)

after the deallocate statement, you'll see that gfortran and NAG print a "T", which I think is fine.

Only fine in the sense that if you read the wording of the standard and see that the status of p becomes undefined (under the assumption that it's actually defined behaviour to deallocate q), calling associated for p already invokes undefined behaviour.

Harald wrote:

If I compile with "ifort -check all -g ifort_ptr_dealloc.f90 -traceback", I get:

forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image              PC        Routine            Line        Source             
a.out              08059984  Unknown               Unknown  Unknown
a.out              0804A66A  MAIN__                      6  ifort_ptr_dealloc.f90
a.out              08049FD6  Unknown               Unknown  Unknown

which I think is also fine, as the deallocate invokes undefined behaviour, as you already mentioned.

The question if this is indeed UB is the whole point of my initial post.

Regards, Thomas

 

0 Kudos
tjahns
Beginner
548 Views

jimdempseyatthecove wrote:

>>Since most other compilers tried (pgfortran 14.7, nagfor 5.3.2(990), gfortran 4.8.2) happen to work I hope this can be resolved.

???

I think you mean happen to fail to report an error.

P was allocated, Q was not.

Since neither P nor Q are ALLOCATABLEs they are only associated to the same object. Depending on the interpretation whether Q is associated with the "whole" of the object ALLOCATEd via P or not, calling DEALLOCATE for Q is fine, and P becomes undefined subsequently, i.e. cannot be used until nullified or otherwise associated again, or deallocating q is invalid as ifort seems to believe.

jimdempseyatthecove wrote:

Consider:

PROGRAM ifort_ptr_dealloc
  REAL, POINTER :: p(:, :, :), q(:, :)
  ALLOCATE(p(5,6,7)) ! *** NOTE 7
  p = 1.0
  q => p(:, :, 1) ! A slice of P not whole of P
  DEALLOCATE(q)
END PROGRAM ifort_ptr_dealloc

What do you expect to happen? From your statement regarding (pgfortran 14.7, nagfor 5.3.2(990), gfortran 4.8.2) I suppose you would expect only the slice of P to be deallocated.

Since the "slice" Q references all of P, it remains to clarify whether that is sufficiently close to "whole" as the standard puts it.

Regards, Thomas

0 Kudos
tjahns
Beginner
548 Views

jimdempseyatthecove wrote:

It may be that the standard permits the "slice identical to whole" to be deletable.

Which is the reason I posted in the first place.

jimdempseyatthecove wrote:

I do not know the internals of Fortran to know if internally the allocations internally have a reference count, and/or a list of references.

If so, then in the original example, the deallocate(q) would also have to disassociate p (and all other pointers). This could be implemented by use of an allocation object, containing something like a void* and a reference count. And the pointers containing an array descriptor and a reference to the allocation object.

Fortran implementations have many freedoms how to implement this internally, but the behaviour you sketch is not permitted: if the deallocate is successful the association status of p becomes undefined and cannot be used without invoking undefined behaviour, especially not for another deallocate. This is not Objective C or Java.

Regards, Thomas

0 Kudos
jimdempseyatthecove
Honored Contributor III
548 Views

Although p becomes undefined, my feelings are it would be convenient to either:

a) disassociate the additional pointer(s) thus causing runtime error (permitted as undefined behavior)

b) leave the additional pointer(s) associated but pointed at location 0  thus causing runtime error (permitted as undefined behavior).

This would permit the programmer to catch early a hidden bug. Yes it adds a tad of overhead. So possibly have a diagnostic option to enforce this behavior.

Jim Dempsey

0 Kudos
Kevin_D_Intel
Employee
548 Views

I updated the internal tracking id in my earlier reply with the id of an earlier reported instance of the defect reported in this thread and which will track any associated fix in a future release. I will update this thread as I learn more.

0 Kudos
Reply