Contents   Index   Search   Previous   Next

13.11.2 Unchecked Storage Deallocation

   [{unchecked storage deallocation} {storage deallocation (unchecked)} {deallocation of storage} {reclamation of storage} {freeing storage} Unchecked storage deallocation of an object designated by a value of an access type is achieved by a call to an instance of the generic procedure Unchecked_Deallocation.]

Static Semantics

   The following language-defined generic library procedure exists:
   type Object(<>) is limited private;
   type Name   is access  Object;
procedure Ada.Unchecked_Deallocation(X : in out Name);
pragma Convention(Intrinsic, Ada.Unchecked_Deallocation);
pragma Preelaborate(Ada.Unchecked_Deallocation);
Reason: The pragma Convention implies that the attribute Access is not allowed for instances of Unchecked_Deallocation.

Dynamic Semantics

   Given an instance of Unchecked_Deallocation declared as follows:
procedure Free is
    new Ada.Unchecked_Deallocation(
   Procedure Free has the following effect:
After executing Free(X), the value of X is null.
Free(X), when X is already equal to null, has no effect.
Free(X), when X is not equal to null first performs finalization, as described in 7.6. It then deallocates the storage occupied by the object designated by X. If the storage pool is a user-defined object, then the storage is deallocated by calling Deallocate, passing access_to_variable_subtype_name'Storage_Pool as the Pool parameter. Storage_Address is the value returned in the Storage_Address parameter of the corresponding Allocate call. Size_In_Storage_Elements and Alignment are the same values passed to the corresponding Allocate call. There is one exception: if the object being freed contains tasks, the object might not be deallocated.
Ramification: Free calls only the specified Deallocate procedure to do deallocation. For any given object deallocation, the number of calls to Free (usually one) will be equal to the number of Allocate calls it took to allocate the object. We do not define the relative order of multiple calls used to deallocate the same object -- that is, if the allocator allocated two pieces x and y, then Free might deallocate x and then y, or it might deallocate y and then x.
    {freed: See nonexistent} {nonexistent} After Free(X), the object designated by X, and any subcomponents thereof, no longer exist; their storage can be reused for other purposes.

Bounded (Run-Time) Errors

    {bounded error (cause) [partial]} It is a bounded error to free a discriminated, unterminated task object. The possible consequences are:
Reason: This is an error because the task might refer to its discriminants, and the discriminants might be deallocated by freeing the task object.
Implementation Note: This last case presumes an implementation where the task references its discriminants indirectly, and the pointer is nulled out when the task object is deallocated.
    In the first two cases, the storage for the discriminants (and for any enclosing object if it is designated by an access discriminant of the task) is not reclaimed prior to task termination.
Ramification: The storage might never be reclaimed.

Erroneous Execution

    {nonexistent} {erroneous execution (cause) [partial]} Evaluating a name that denotes a nonexistent object is erroneous. The execution of a call to an instance of Unchecked_Deallocation is erroneous if the object was created other than by an allocator for an access type whose pool is Name'Storage_Pool.

Implementation Advice

    For a standard storage pool, Free should actually reclaim the storage.
Ramification: This is not a testable property, since we do not how much storage is used by a given pool element, nor whether fragmentation can occur.
26  The rules here that refer to Free apply to any instance of Unchecked_Deallocation.
27  Unchecked_Deallocation cannot be instantiated for an access-to-constant type. This is implied by the rules of 12.5.4.

Contents   Index   Search   Previous   Next   Legal