Ada provides a generic procedure to release an object if it's no longer being referenced. This procedure is equivalent to ``free'' in C and ``delete'' in C++. This generic procedure's name is ``Unchecked_Deallocation''. Since it's a generic, you need to instantiate the generic using the access type you're using. By convention, the name of the instantiation is usually called "Free".
Here's the official definition of generic procedure Unchecked_Deallocation:
generic type Object(<>) is limited private; type Name is access Object; procedure Unchecked_Deallocation(X : in out Name);
Note that we need to pass it two things; a type, and the access to that type. Here's a simple example - let's instantiate a procedure called ``Free'' that will let us release objects when they're no longer used:
procedure Free is new Unchecked_Deallocation(Tree_Node, Tree_Access);
Now that we've instantiated a procedure called ``Free'', we can call it. Let's continue our example; imagine that we don't want to use the node we created in the last section any more. That's fine, we'll just call the new ``Free'' routine we've created:
Free(Current);
When Free returns, the variable Current will have the value "null", and the memory previously accessed by Current will have been released. Any instantiation of Unchecked_Deallocation will automatically call any finalization operations defined for the enclosed types, as you would expect.
An important problem arises here that also arises in other languages such as C, C++, and Pascal: what if there's another access type that refers to that object? In our example, the access variable ``Root'' still refers to an object, but that object no longer exists. Any attempt to use Root to access its object may result in unpredictable behavior. While Ada provides a number of protections in the use of access variables, this is one problem which Ada (as well as some other languages) doesn't completely protect against.
This is an area where there is a strong tension between the desire to be safe and easy to use versus the desire to be predictably efficient. Some languages require deallocation to be handled automatically; this is called automatic garbage collection. Examples of such languages include Smalltalk, Eiffel, and Java. Automatic garbage collection is really convenient, so why wouldn't everyone want it? Well, the problem with automatic garbage collection is that:
The Ada specification does not require automatic garbage collection, but Ada is explicitly defined to permit automatic garbage collection. Compiler vendors are free to implement it at their option. Ada does require that Unchecked_Deallocation be available, which will do nothing if there's an automatic garbage collector. If you're using an Ada compiler that doesn't do automatic garbage collection (true for most) and you're concerned about a incorrect deallocation, you can search for all uses of Unchecked_Deallocation.
Unchecked_Deallocation works just fine on any object, including arrays.
Which of the following statements is true?
![]() |
![]() |
![]() |
---|
David A. Wheeler (dwheeler@ida.org)