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 that used to be used by the Tree_Node 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 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 Ada doesn't completely protect against.
This is one 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:
In Ada, the solution is to not require automatic garbage collection, but instead Ada is defined to explicitly permit automatic garbage collection and 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 bad deallocation, you can search for all uses of Unchecked_Deallocation.
Unchecked_Deallocation works just fine on any object, including arrays.
There is no quiz question for this section.
You may go to the next section.
Go back to the previous section
Go up to the outline of lesson 12
David A. Wheeler (wheeler@ida.org)