A pointer passed to DEALLOCATE points to an object that cannot be deallocated

A pointer passed to DEALLOCATE points to an object that cannot be deallocated

Compiling (with ifort 13.1.1) and executing the following code

module tt
  type :: t
  end type t
  type :: t1
     class(t), pointer :: tp
   contains
     procedure :: set
     procedure :: unset
  end type t1
contains
  function t_new() result(r)
    type(t), pointer :: r
    allocate(r)
  end function t_new
  subroutine set(a, tp)
    class(t1) :: a
    class(t), target :: tp
    a%tp => tp
  end subroutine set
  subroutine unset(a)
    class(t1) :: a
    print *, "Dealocating"
    deallocate(a%tp)
    print *, "Deallocated"
  end subroutine unset
end module tt
program test
  use tt
  type(t1) :: a
  call a%set(t_new())
  call a%unset()
end program test

I get

 Dealocating
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image              PC                Routine            Line        Source             
pointer            000000000046D7AE  Unknown               Unknown  Unknown
pointer            000000000046C246  Unknown               Unknown  Unknown
pointer            0000000000424FC2  Unknown               Unknown  Unknown
pointer            00000000004068BB  Unknown               Unknown  Unknown
pointer            00000000004050E6  Unknown               Unknown  Unknown
pointer            0000000000402C57  Unknown               Unknown  Unknown
pointer            0000000000402B3C  Unknown               Unknown  Unknown
libc.so.6          00007FB324690A15  Unknown               Unknown  Unknown
pointer            0000000000402A39  Unknown               Unknown  Unknown

but using gfortran yields

 Dealocating
 Deallocated

Is this a bug?

Best,

Paweł Biernat

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Yes, it is a bug. I have escalated it as issue DPD200243572. A workaround is to have t_new return a class(t) pointer that is allocated as type(t), for example:

  function t_new() result(r)
   class(t), pointer :: r
    allocate(t::r)
  end function t_new 

Retired 12/31/2016

Thanks, I will use the workaround.

Paweł

Steve,

Why is scoping required on the allocate?

Jim Dempsey

www.quickthreadprogramming.com

Jim, if you mean the t::, that specifies the dynamic type of the allocated polymorphic object. It is not strictly necessary in this case, as without it the declared type t is used anyway, but I like to put it in there for clarity when allocating a polymorphic object.

Retired 12/31/2016

An alternative workaround, and one I think is "more correct", is to make the tp argument to set a pointer rather than target. The problem is that anything could be a target and not necessarily something that was allocated. We need to look at this closer and it may be a while before we have an answer. But regardless, I think pointer is the right thing to use in set.

Retired 12/31/2016

In F2003 (specifically), can the value that results from the evaluation of an expression have the target attribute?

No - "An entity with the TARGET attribute shall be a variable" (C555 in F2008)

I discussed this with the developers and their position is that the current behavior is correct - doing a pointer assignment to something that isn't a pointer loses the ability to deallocate it later through that pointer, even if that thing was itself allocated. I am going to be out the next three weeks and will have to defer study of what the standard says about this until I get back.

Retired 12/31/2016

So is the statement

call a%set(t_new())

valid in F2008 at all? Should I avoid using the result of a function as an argument this way and introduce temporary variable instead?

class(t), pointer :: tmp
tmp=>t_new()
call a%set(tmp)

Paweł

That specific statement is valid F2003/F2008, the problem is what happens afterwards, particularly when the set procedure finishes.  I think in F2003 the pointer association status of the tp component becomes undefined - this is because the dummy argument that it is pointed at is associated with an actual argument that is an expression, as part of the call that expression is evaluated, evaluation of an expression produces a value, as Steve says - a value cannot be a target, when you have a non-target actual associated with a target dummy the pointer association status of things pointed at the dummy becomes undefined when the procedure terminates.

In F2008 a variable can be a function reference that has a data pointer result (which I don't think ifort does yet, but I think gfortran does).  A variable can be a target - whatever the function result points at has to have had the target attribute.  So you have a target actual with a target dummy.  So things are ...umm... different.  After that - I get confused and give up.  Part of my confusion resulted in a post to c.l.f.

Edit to note that the first paragraph above is all wrong.  See interp F95/0074 case 3.

Leave a Comment

Please sign in to add a comment. Not a member? Join today