From: Daniel Kraft on
Hi,

while reading through the Draft Standard (about automatic deallocation
of allocated, allocatable entities and finalization) there were some
points I'm unsure about. Say, I've types like that:

TYPE :: finalizable_t
CONTAINS
FINAL :: some_rank_1_finalizer
END TYPE finalizable_t

TYPE :: compound_t
TYPE(finalizable_t), ALLOCATABLE :: vector(:)
END TYPE compount_t

Now, look at a method like this:

SUBROUTINE test ()
IMPLICIT NONE

TYPE(compound_t) :: static
TYPE(compound_t), ALLOCATABLE :: dynamic(:)

ALLOCATE (dynamic(42))
ALLCOATE (dynamic(5)%vector(20))
ALLOCATE (static%vector(20))

END SUBROUTINE test

When test ends, dynamic is allocated and thus automatic deallocation
takes place; as vector is an ALLOCATABLE component, dynamic(5)%vector
will be deallocated, too (as it's the only one which is actually allocated).

But as I read the standard, static%vector will *not* be automatic
deallocated as the standard says about the automatic deallocation of
components:

"When a varaible of derived type is deallocated, any allocated
allocatable subobject is deallocated."

So this mentions explicitelly "is deallocated" which is not fulfilled in
the case of static, is it? So that's why I reason that here
static%vector should *not* be auto-deallocated.

Is this correct? And if so, is there a reason for what seems to me to
be inconsistent behaviour, what did I overlook?

And another one: When doing an intrinsic assignment, the LHS is
finalized before it is overwritten. In case of auto-deallocation, it is
not itself deallocated, but its allocated allocatable components are
deallocated. Right?

In any case, each finalizable_t entity is finalized before it is
(auto-)deallocated, and in my example these are the only places were it
is to be finalized. Did I get this correct?

Thanks for your clarification!

Daniel

--
Done: Bar-Sam-Val-Wiz, Dwa-Elf-Hum-Orc, Cha-Law, Fem-Mal
Underway: Ran-Gno-Neu-Fem
To go: Arc-Cav-Hea-Kni-Mon-Pri-Rog-Tou
From: Damian on
On Jun 21, 7:06 am, Daniel Kraft <d...(a)domob.eu> wrote:
> Hi,
>
> while reading through the Draft Standard (about automatic deallocation
> of allocated, allocatable entities and finalization) there were some
> points I'm unsure about. Say, I've types like that:
>
> TYPE :: finalizable_t
> CONTAINS
> FINAL :: some_rank_1_finalizer
> END TYPE finalizable_t
>
> TYPE :: compound_t
> TYPE(finalizable_t), ALLOCATABLE :: vector(:)
> END TYPE compount_t
>
> Now, look at a method like this:
>
> SUBROUTINE test ()
> IMPLICIT NONE
>
> TYPE(compound_t) :: static
> TYPE(compound_t), ALLOCATABLE :: dynamic(:)
>
> ALLOCATE (dynamic(42))
> ALLCOATE (dynamic(5)%vector(20))
> ALLOCATE (static%vector(20))
>
> END SUBROUTINE test
>
> When test ends, dynamic is allocated and thus automatic deallocation
> takes place; as vector is an ALLOCATABLE component, dynamic(5)%vector
> will be deallocated, too (as it's the only one which is actually allocated).
>
> But as I read the standard, static%vector will *not* be automatic
> deallocated as the standard says about the automatic deallocation of
> components:
>
> "When a varaible of derived type is deallocated, any allocated
> allocatable subobject is deallocated."
>
> So this mentions explicitelly "is deallocated" which is not fulfilled in
> the case of static, is it? So that's why I reason that here
> static%vector should *not* be auto-deallocated.
>
> Is this correct? And if so, is there a reason for what seems to me to
> be inconsistent behaviour, what did I overlook?
>
> And another one: When doing an intrinsic assignment, the LHS is
> finalized before it is overwritten. In case of auto-deallocation, it is
> not itself deallocated, but its allocated allocatable components are
> deallocated. Right?
>
> In any case, each finalizable_t entity is finalized before it is
> (auto-)deallocated, and in my example these are the only places were it
> is to be finalized. Did I get this correct?
>
> Thanks for your clarification!
>
> Daniel
>
> --
> Done: Bar-Sam-Val-Wiz, Dwa-Elf-Hum-Orc, Cha-Law, Fem-Mal
> Underway: Ran-Gno-Neu-Fem
> To go: Arc-Cav-Hea-Kni-Mon-Pri-Rog-Tou

I don't think the phrase "is deallocated" necessarily refers to
explicit deallocation.



The May 2004 draft of the standard, section 6.3.3.1, line 15 states,

"If an allocatable component is a subobject of a finalizable object,
that object is finalized before the component is automatically
deallocated.

The effect of automatic deallocation is the same as that of a
DEALLOCATE statement without a dealloc-opt-list."

My interpretation of the first sentence is that the allocatable
component static%vector(20) will be deallocated. Of course, this must
be referring to an automatic deallocation because the entity must be
out of scope for finalization to occur and the user can't explicitly
deallocate something that is out of scope. My interpretation of the
second sentence is that there is no difference between an automatic
deallocation and explicit deallocation without a dealloc-opt-list.

Damian
From: Daniel Kraft on
Damian wrote:
> On Jun 21, 7:06 am, Daniel Kraft <d...(a)domob.eu> wrote:
>> TYPE :: finalizable_t
>> CONTAINS
>> FINAL :: some_rank_1_finalizer
>> END TYPE finalizable_t
>>
>> TYPE :: compound_t
>> TYPE(finalizable_t), ALLOCATABLE :: vector(:)
>> END TYPE compount_t
>>
>> Now, look at a method like this:
>>
>> SUBROUTINE test ()
>> IMPLICIT NONE
>>
>> TYPE(compound_t) :: static
>> TYPE(compound_t), ALLOCATABLE :: dynamic(:)
>>
>> ALLOCATE (dynamic(42))
>> ALLCOATE (dynamic(5)%vector(20))
>> ALLOCATE (static%vector(20))
>>
>> END SUBROUTINE test
>
> I don't think the phrase "is deallocated" necessarily refers to
> explicit deallocation.

So you mean "is deallocated" can also refer to goind out of scope?

>
> The May 2004 draft of the standard, section 6.3.3.1, line 15 states,
>
> "If an allocatable component is a subobject of a finalizable object,
> that object is finalized before the component is automatically
> deallocated.
>
> The effect of automatic deallocation is the same as that of a
> DEALLOCATE statement without a dealloc-opt-list."
>
> My interpretation of the first sentence is that the allocatable
> component static%vector(20) will be deallocated. Of course, this must
> be referring to an automatic deallocation because the entity must be
> out of scope for finalization to occur and the user can't explicitly
> deallocate something that is out of scope. My interpretation of the
> second sentence is that there is no difference between an automatic
> deallocation and explicit deallocation without a dealloc-opt-list.

Hi Damian,

my personal reading of the first paragraph you quoted is that static
will be finalized before every event that will automatically deallocate
static%vector, which seams reasonable to me. But it is not clear to me,
that static%vector should be deallocated after every event that causes
finalization.

And in my original interpretation, while static will be finalized when
going out of scope, static%vector will never be automatically
deallocated. OTOH, would static have been allocatable and allocated, it
*and* static%vector would both be deallocated.

Daniel

--
Done: Bar-Sam-Val-Wiz, Dwa-Elf-Hum-Orc, Cha-Law, Fem-Mal
Underway: Ran-Gno-Neu-Fem
To go: Arc-Cav-Hea-Kni-Mon-Pri-Rog-Tou
From: Tobias Burnus on
On Jun 22, 9:29 am, Daniel Kraft <d...(a)domob.eu> wrote:
> >> SUBROUTINE test ()
> >>    IMPLICIT NONE
> >>    TYPE(compound_t) :: static
> >>    TYPE(compound_t), ALLOCATABLE :: dynamic(:)
>
>  But it is not clear to me,
> that static%vector should be deallocated after every event that causes
> finalization.

The standard is crafted such that (except for POINTERS) a program
cannot leak memory. If one finds one example, which can leak memory,
it (usually) means that one has either misread the standard.

As "static" has no "SAVE" attribute, the components of it will be
deallocated as soon as the END is encountered. (This is by the way
also what gfortran does.)


I admit it is not trivial to read the standard:

"16.5.6 Events that cause variables to become undefined"
[...] "When the execution of a procedure is terminated by execution of
a RETURN or END statement, an allocatable variable that is a named
local variable of the procedure retains its allocation and definition
status if it has the SAVE attribute or is a function result variable
or a subobject thereof; otherwise, it is deallocated."


Tobias
From: Daniel Kraft on
Tobias Burnus wrote:
> On Jun 22, 9:29 am, Daniel Kraft <d...(a)domob.eu> wrote:
>>>> SUBROUTINE test ()
>>>> IMPLICIT NONE
>>>> TYPE(compound_t) :: static
>>>> TYPE(compound_t), ALLOCATABLE :: dynamic(:)
>> But it is not clear to me,
>> that static%vector should be deallocated after every event that causes
>> finalization.
>
> The standard is crafted such that (except for POINTERS) a program
> cannot leak memory. If one finds one example, which can leak memory,
> it (usually) means that one has either misread the standard.
>
> As "static" has no "SAVE" attribute, the components of it will be
> deallocated as soon as the END is encountered. (This is by the way
> also what gfortran does.)
>
> I admit it is not trivial to read the standard:
>
> "16.5.6 Events that cause variables to become undefined"
> [...] "When the execution of a procedure is terminated by execution of
> a RETURN or END statement, an allocatable variable that is a named
> local variable of the procedure retains its allocation and definition
> status if it has the SAVE attribute or is a function result variable
> or a subobject thereof; otherwise, it is deallocated."

I read that one, but for me "local variables" are only real local
variables; or do components of local variables count, too? So I see
"static" as a local variable, but static%vector not. Is that wrong?

What's about this one:

TYPE :: test1
INTEGER, ALLOCATABLE :: vector(:)
END TYPE test1

TYPE :: test2
TYPE(test1) :: static
END TYPE test2

TYPE(test2) :: static2
ALLOCATE(static2%static%vector(5))

END

Will vector here be auto-deallocated, even though it's one level deeper
nested? BTW, just tell me and I'll update my patch accordingly.

Daniel

--
Done: Bar-Sam-Val-Wiz, Dwa-Elf-Hum-Orc, Cha-Law, Fem-Mal
Underway: Ran-Gno-Neu-Fem
To go: Arc-Cav-Hea-Kni-Mon-Pri-Rog-Tou