two questions on allocatable member fields

Janus Weil janus@gcc.gnu.org
Wed Mar 6 10:42:00 GMT 2013


Heya,

> Sorry for asking perhaps too RTFM-ish questions here...:
>
> Are (according to the standard, and in practice in gfortran) allocated
> allocatable member fields deallocated automatically when an instance of a
> type goes out of scope?

Yes to both (it depends a bit, but for your example, the answer is
yes). The behavior of gfortran you can easily check via
-fdump-tree-original, which for your test case shows code like this
being generated:

        if (i.r.data != 0B)
          {
            __builtin_free ((void *) i.r.data);
          }
        i.r.data = 0B;



> For example, with the code below:
>
> ------------------------------------------------------------
> module m
>   implicit none
>
>   type :: t
>     real, allocatable :: r(:)
>     contains
>     procedure :: init => init
>   end type
>
>   contains
>
>   subroutine init(this)
>     class(t) :: this
>     allocate(this%r(1024))
>   end subroutine
> end module
>
> program test
>   use m
>   implicit none
>   block
>     type(t) :: i
>     call i%init()
>   end block
> end
> ------------------------------------------------------------
>
> would i%r be deallocated at the last "end block", or is it necessary to call
> deallocate() explicitly through some destructor-like method?

No explicit DEALLOCATE statement needed, since the Fortran standard
requires auto-deallocation here. Have a look at F08 section 6.7.3.2.

Note: gfortran currently even does the auto-deallocation if the BLOCK
statement is left out. As a matter of fact this is in conflict with
the F08 standard (cf. PR 55207). I personally never really understood
why automatic deallocation (and finalization) is not required for
variables in the scope of the main program, but that's the way it is
...


> And a related question: an allocatable member of a type cannot be declared
> as a target. How to point a pointer to an allocatable member of a type?
>
> For example (extension of the code above):
> ------------------------------------------------------------
> module m
>   implicit none
>
>   type :: t
>     real, allocatable :: r(:) ! cannot be a target
>     contains
>     procedure :: init => init
>     procedure, nopass :: prnt => prnt
>   end type
>
>   contains
>
>   subroutine init(this)
>     class(t) :: this
>     real, pointer :: p(:)
>
>     allocate(this%r(1024))
>     p => this%r(1:10)
>     call prnt(p)
>   end subroutine
>
>   subroutine prnt(ptr)
>     real, pointer :: ptr(:)
>     print*, ptr
>   end subroutine
> end module
> ------------------------------------------------------------
>
> gives:
>
> ------------------------------------------------------------
>     p => this%r(1:10)
>          1
> Error: Pointer assignment target is neither TARGET nor POINTER at (1)
> ------------------------------------------------------------
>
> but making t%r a target is impossible:
>
> ------------------------------------------------------------
>     real, allocatable, target :: r(:) ! cannot be a target
>                              1
> Error: Attribute at (1) is not allowed in a TYPE definition
> ------------------------------------------------------------
>
> Is there any way around it?

How about making 'this' a target?

    class(t), target :: this

In fact, this makes the error go away ...

Cheers,
Janus



More information about the Fortran mailing list