- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The code below does not call the object finalization code in ifort 14.0.1, and I think it should. I've submitted it as issue 6000044034 last year, but still seem to be stuck in "investigating" limbo.
module A
Type T
integer :: val = 2
contains
final :: testfree
end type
contains
subroutine testfree(this)
Type(T) this
print *,'freed'
end subroutine
subroutine Testf()
associate(X => T())
print *, X%val
end associate
print *,'ended'
end subroutine Testf
end module
program tester
use A
call Testf
end program
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The data type has to have an ALLOCATABLE attribute in order for the finalizer to be invoked. The following code with a minor change to use an allocatable variable works ok.
MODULE A
TYPE T
INTEGER :: VAL = 2
CONTAINS
FINAL :: testfree
END TYPE
CONTAINS
SUBROUTINE testfree(this)
TYPE(T) this
PRINT *,'freed'
END SUBROUTINE
SUBROUTINE Testf()
TYPE(T), ALLOCATABLE :: foo
foo = T()
ASSOCIATE (X => foo)
PRINT *, X%VAL
END ASSOCIATE
PRINT *,'ended'
END SUBROUTINE Testf
END MODULE
PROGRAM tester
USE A, ONLY : Testf
CALL Testf
END PROGRAM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I agree it works fine if it is a local variable. But I don't think there's any requirement for the type to be allocatable, the F08 standard says
16 4.5.6.3 When finalization occurs
17 1 When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalized.
18 2 A nonpointer, nonallocatable object that is not a dummy argument or function result is finalized immediately
19 before it would become undefined due to execution of a RETURN or END statement (16.6.6, item (3)).
Point 18 suggests here that it should be finalized at the latest at subroutine exit (and I think probably at the end of the associate scoping block). Btw, the motivation was I was thinking of using constructions like
associate (F => TTextFile('myfile.txt'))
call F%Write(myData)
end associate
and have TTextFile's finalization routine autoamtically close the internal file handle.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I assume you think the finalizer should be called based on the following text in the original F2008 standard:
4.5.6.3 When finalization occurs
5 If an executable construct references a structure constructor or array constructor, the entity created by the constructor is finalized before execution of the executable constructs in the scoping unit.
This text was deleted in F2008 Corrigendum 1 as part of interpretation F08/0011. Here is the text of that:
NUMBER: F08/0011
TITLE: How many times are constructed values finalized?
KEYWORDS: Finalization
DEFECT TYPE: Erratum
STATUS: Passed by WG5 letter ballot
QUESTION:
Consider the program:
Module m
Type t1
Real c
Contains
Final :: f10,f11
End Type
Type,Extends(t1) :: t2
Real d
Contains
Final :: f20,f21
End Type
Contains
Subroutine f10(x)
Type(t1),Intent(InOut) :: x
Print *,'f10 called'
End Subroutine
Subroutine f11(x)
Type(t1),Intent(InOut) :: x(:)
Print *,'f11 called'
End Subroutine
Subroutine f20(x)
Type(t2),Intent(InOut) :: x
Print *,'f20 called'
End Subroutine
Subroutine f21(x)
Type(t2),Intent(InOut) :: x(:)
Print *,'f21 called'
End Subroutine
End Module
Program q
Call sub(1.5,2.5)
End Program
Subroutine sub(x,y)
Use m
Type(t1),Parameter :: p1 = t1(2.5)
Type(t2),Parameter :: p2 = t2(3.5,-3.5)
Call s10(t1(x))
Call s11([p1]) ! (a)
Call s11([t1(x)]) ! (b)
Call s11([ [ [ p1,p1 ] ] ]) ! (c)
Call s20(t2(x,y))
Call s21([p2]) ! (d)
Call s21([t2(y,y)]) ! (e)
Call s21([t2(t1=p1,y)]) ! (f)
Call s21([t2(t1=t1(x),y)]) ! (g)
Call s21([(p2,t2(x,y),i=1,10**7)]) ! (h)
End Subroutine
The topic is how many times each final procedure is called on return
from each subroutine?
For s10, clearly f10 is called once.
For s11(a), clearly f11 is called once, and f10 is not called.
For s11(b), the standard (4.5.6.3 para 5) seems to indicate that f10
is called. That would not make much sense - the value of the
structure constructor is part of the value of the array constructor,
so calling f10 would mean that that array element would be finalized
twice (once by f11, once by f10, in no set order).
For s11(c), the standard standard appears to say that f11 is called
three times, once for each (nested) array constructor. Seeing as
how nesting array constructors is a syntactic thing that makes zero
difference to the value - the value of [[anything]] is identical in
every respect to the value of [anything] - this does not seem to
make sense.
For s20, clearly f20 is called once, and f10 is called afterwards to
finalize the parent component.
For s21(d), clearly f21 is called once, followed by f11 to finalize the
parent components. f20 and f10 are not called.
For s21(e), f21 and f11 are called as in s21(d); the standard implies
that f20 and then f10 are called, but that does not make sense, the
same as case s11(b).
For s21(f), the situation seems to be the same as s21(e); the wanted
f21 and f11, and (unordered) the unwanted f20 and f10.
For s21(g), f21 and f11 are called as in s21(d); the standard implies
that f10 is called to finalize t1(3) and also that f20 and then f10
are called to finalize t2(t1=t1(3),4). This makes even less sense
than before, since the t1 part of the array constructor element is
going to be finalized 3 times just because of the syntax we used.
For s21(h), f21 and f11 are called as in s21(d) to finalize the whole
array constructor value; the standard also implies that f20 and then
f10 are called on all of the 5000000 even-numbered elements.
Requiring the processor to keep track of all those elements to be
finalized on return from s21 seems rather severe.
Furthermore, an object that has been finalized is not permitted to be
referenced or defined. That makes the multiple finalization
interpretation even more hard to understand.
Philosophically, finalization should finalize objects exactly once.
There seem to be three possibilities here.
(1) The finalizers are called multiple times, but on the separate
entities created by the constructors. For example s21(g), that is
t1(3) is created as object X, when t2(...) is evaluated a new
separate object Y is created and that value is copied into it, and
when [...] is evaluated a third object Z is created with the value
of Y copied into it; afterwards, we effectively have
call f10(X); call f20(Y); call f21(Z); call f11(Z%t1)
For s21(h) that burden is going to be extreme because the standard
says these are "finalized after execution of the innermost
executable construct containing the reference" (and it is possible
to detect this in a conforming program); changing that to
"finalized after the value has been used" would be better if
slightly vague.
(2) These entities are indeed finalized multiple times, just as the
standard implies.
(3) Constructors that are merely providing part of the value of a
bigger constructor are not finalized.
(4) Constructors should never be finalized in themselves, this was
just a design error that inevitably leads to multiple or
unwanted finalization.
Which is the correct approach?
ANSWER:
Approach 4. Constructors don't do anything that needs finalization.
Edits are provided to correct the mistake.
NOTE: This answer subsumes interp F08/0012 (10-159r1).
EDITS to 10-007r1:
[24:9] Change the first word of 1.6.2p1
"This" -> "Except as identified in this subclause, this".
[24:11+] Insert new paragraph after 1.6.2p1:
"Fortran 2003 specified that array constructors and structure
constructors of finalizable type are finalized. This part of
ISO/IEC 1539 specifies that these constructors are not
finalized.".
[76:17-18,21-22] Delete paragraphs 5 and 7 of 4.5.6.3
(When finalization occurs).
SUBMITTED BY: Malcolm Cohen
HISTORY: 10-158 m192 F08/0011 submitted
10-158r1 m192 Revised - Passed by J3 meeting
10-202 m192 Passed as amended by J3 letter ballot
#21 10-199
11-006Ar1 m196 Adjust edits to reference 10-007r1
N1878 Passed by WG5 letter ballot
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve for the standard update, interesting.
The level of support you provide here is amazing, I wish the official support channels were equally responsive (my issue 0000456671, still a regular annoyance, dates back to 2007!) - it seems like it is always much better to post here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry to hear that you've had issues with Intel Premier Support. I pinged the support engineer who owned this issue. I sometimes lose track of issues I'm supposed to be working (the tool we use doesn't forget, but if I don't look at it....)
Regarding 456671, this was escalated to development, as was noted. As Patrick said in the last update there, the behavior of Visual Studio regarding "step over" or "run to cursor" in the debugger is not something under our control. I think the problem here is that a LOT of instructions can be executed for an array assignment, and if the debugger is single-stepping, which it sometimes does, that can take a long time.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page