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