Wednesday, September 26, 2012

AdaTutor - Advanced Topics (7)

Unchecked Conversion and Unchecked Deallocation

Ada comes with a generic function Ada.Unchecked_Conversion and a generic procedure Ada.Unchecked_Deallocation.  (In Ada 83, the names don't contain Ada., and Ada 95 accepts the shorter names for compatibility.)  They can be instantiated for any type.  Both are somewhat dangerous to use, but we'll describe them briefly.  Their specifications (slightly simplified) are below; the Ada 83 specifications don't have (<>).

   generic
      type Source(<>) is limited private;
      type Target(<>) is limited private;
   function Ada.Unchecked_Conversion(S : Source) return Target;

   generic
      type Object(<>) is limited private;
      type Name       is access Object;
   procedure Ada.Unchecked_Deallocation(X : in out Name);

Ada.Unchecked_Conversion "converts" from one type to another without doing any arithmetic or bit manipulation, letting us look at an object of one type as if it were of another type.  (This is similar to using EQUIVALENCE in Fortran.)

The results of using Ada.Unchecked_Conversion may be unpredictable if the two types don't occupy the same amount of storage.

One use of Ada.Unchecked_Conversion might be to allow us to and two Integers.  (Ada 95 allows us to and two objects of a modular type, but not two Integers.) Some Ada compilers come with a package that enables us to and two Integers, but many compilers have no such package.  Suppose that types Integer and Boolean occupy the same amount of storage.  If our program says with Ada.Unchecked_Conversion; we could write

function Int_To_Bool is new Ada.Unchecked_Conversion(Integer, Boolean);
function Bool_To_Int is new Ada.Unchecked_Conversion(Boolean, Integer);
function "and"(Left, Right : in Integer) return Integer is
begin
   return Bool_To_Int(Int_To_Bool(Left) and Int_To_Bool(Right));
end "and";

Using Ada.Unchecked_Conversion usually destroys program portability.

Ada.Unchecked_Deallocation allows us to free the memory occupied by an object accessed through an access type.  Some systems automatically reclaim memory when it's needed.  However, the execution time for that so-called garbage collection tends to be long and unpredictable.  Suppose we have type P is access Link; and Ptr : P;.  Also suppose that we no longer need the object accessed by Ptr and we're sure that no other objects access the same object as Ptr.  If our program says with Ada.Unchecked_Deallocation; we can write

procedure Free is new Ada.Unchecked_Deallocation(Link, P);
...
Free(Ptr);
This will release the memory occupied by the object accessed by Ptr, and then set Ptr to null.  But there's a danger.  If there's another object that accessed what Ptr accessed, it now accesses released memory.  A reference through such an object will have unpredictable results.  In general, it's best to let the system handle the reclaiming of memory.  That way there's no danger of dangling references.

< prev   next >

No comments: