X3J3/94-270r3 Subject: Automatic deallocation of ALLOCATABLE objects References: WG5-N930, Resolutions of the Berchtesgaden WG5 Meeting, B9 WG5-N931, Requirements for Allowing Allocatable derived-type Components Revision History: 94-270r1, examples added, initial status text moved here from 94-269 94-270, specific edits added 94-211, original presentation, May 1994 (meeting 129) Requirement Title: B9/B3 Allocatable derived-type components Status: For consideration Technical Description: Require automatic deallocation of unSAVEd allocatable objects on scope exit. Motivation: Currently, the standard does not provide for automatic deallocation of allocatable objects, even when they are local non-static variables. When such objects go out of scope a memory leak can occur. The general handling of ALLOCATABLE is being regularised; removing surprises is part of the task. Further, the general thrust of the Fortran committee is to work to eliminate memory leakage opportunities. The main reason for the current situation appears to be a concern about performance. The addition of automatic (i.e. managed by the processor rather than the user) deallocation will not have a major performance impact. The actual deallocation is what takes time, and that must occur in any event if a memory leak is to be avoided. The proposed change merely adds a check on whether the deallocation is required -- a few instructions at most, compared with dozens of instructions for the actual deallocation. Note further that we have already accepted the "overhead" of explicit "initialisation" of the allocation state of allocatable variables. This initialisation was necessary to bring a semblance of order into the allocation status. By adding automatic deallocation, we not only remove a source of user annoyance and surprise, but also simplify the language definition. Currently, there must be a third ("undefined") allocation state for allocatable objects and fairly confusing words about the consequences of going out of scope with a non- deallocated object. Finally, as the language currently stands it is impossible to create opaque data types which need a variable amount of storage without the possibility of leaking memory. In conjunction with the allocatable component proposal (94- 269r2) automatic deallocation of allocatable objects provides the user with this capability in a form which is safe to use. Detailed EDITS: Subclause 6.3.3.1 [69:12-15] {allocation status} {{the third and fourth paragraphs of 6.3.3.1}} {{specify we lose the old allocatable array on each new instantiation if not SAVEd}} replace with: "Any other allocated allocatable array that is a local variable of a procedure, is not a subobject of a pointer, is not accessed by use association, is not part of a dummy argument, is not part of a function return value, and is not a variable accessed from the host scoping unit is deallocated (as if by a DEALLOCATE statement)." [69:13+] {allocation status} {{allow modules to always SAVE their allocatable arrays, or to always initialise them (e.g. if they are implemented via overlay segments), but do not penalise the user by forbidding subsequent access}} add a new paragraph: "The allocation status of any other allocatable array that is a local variable of a module is processor-defined; the ALLOCATED intrinsic may be used to determine whether the array is still currently allocated or has been deallocated." [69:15+] {deallocation action} {{Here we define deallocation of an object containing allocatable components to deallocate any of these which happen to be allocated. Since this is described recursively, a nested tree of allocatable components will be deallocated bottom-up. Note that a system which stores allocatable objects on a stack or which performs automatic garbage collection already satisfies this definition.}} insert new paragraph: "When a derived-type object is deallocated, any ultimate allocatable components that are currently allocated are deallocated. [Footnote: in the following example: MODULE USER TYPE, PRIVATE :: VARYING_STRING CHARACTER,ALLOCATABLE :: VALUE(:) END TYPE TYPE USER PRIVATE TYPE(VARYING_STRING) NAME TYPE(VARYING_STRING),POINTER :: DETAILS(:) END TYPE ... END MODULE SUBROUTINE PROCESS_ONE_USER USE USER TYPE(USER) X CALL READ_USER(X) ! Read user details into X ... ! Process the user END SUBROUTINE on return from PROCESS_ONE_USER, X does not have the SAVE attribute and so X%NAME%VALUE is deallocated. However, X%DETAILS has the POINTER attribute and so its target and any of the target~s components are not automatically deallocated.] Subclause 14.8 [252:37-253:4] {{remove undefined allocation status from the possibilities, to avoid never-never land}} replace existing text with: "(1) Not currently allocated. An allocatable object with this status must not be referenced, defined, or deallocated; it may be allocated with the ALLOCATE statement. The ALLOCATED intrinsic returns .FALSE. for such an object. (2) Currently allocated. An allocatable object with this status may be referenced, defined, or deallocated; it must not be allocated. The ALLOCATED intrinsic returns .TRUE. for such an object. An allocatable array with the SAVE attribute has an initial status of not currently allocated. An ALLOCATE statement changes this status to currently allocated; it then remains currently allocated until execution of a DEALLOCATE statement. An allocatable array component of a derived-type variable that has the POINTER attribute, or is a subobject of a pointer component, has no initial allocation status, because it does not exist until brought into existence by the ALLOCATE statement (or referred to by the pointer assignment statement). Any other allocatable array without the SAVE attribute that is a local variable of a procedure, is not accessed by use association, is not part of a dummy argument, and is not a variable accessed from the host scoping unit has a status of not currently allocated at the beginning of each invocation of the procedure. During execution of the procedure its status may be changed by execution of ALLOCATE and DEALLOCATE statements. On exit from the procedure by execution of a RETURN or END statement, if such an allocatable array is not part of a function return value and has the status of currently allocated, it is deallocated (as if by a DEALLOCATE statement). Any other allocatable array without the SAVE attribute that is a local variable of a module has an initial status of not currently allocated. If the array has an allocation status of currently allocated on execution of a RETURN or END statement resulting in no executing scoping unit having access to the module it is processor-defined whether the array~s allocation status remains currently allocated or the array is deallocated (6.3.3.1) as if by a DEALLOCATE statement." add to Rationale Section: ------------------------- 6.3.3.1 Deallocation of allocatable arrays Automatic deallocation of allocatable arrays (including allocatable array components) provides the user with a safe method of creating opaque data types of variable size which do not leak memory. It also removes the burden of manual storage deallocation both for simple allocatable arrays and for allocatable components of non-opaque types. The "undefined" allocation status of Fortran 90 meant that an allocatable array could easily get into a state where it could not be further used in any way whatsoever, it could not be allocated, deallocated, referenced, defined, or even used as the argument to the ALLOCATED function. Removal of this status provides the user with a safe way of handling allocatable arrays which he does not desire to be SAVEd, permitting use of the ALLOCATED intrinsic function to discover the current allocation status of the array at any time.