Ada Programming/Types/access (Redirected from Ada Programming/Memory)
Different access types
Pool access
Handles an access to an object which was created on one specific heap (or storage pool as it is called in Ada). May not point to a stack or library level (static) object.
type Day_Of_Month is range 1 .. 31;
type Day_Of_Month_Access is access Day_Of_Month;
Access all
Handles an access to an object which was created on any storage pool, on the stack or at library level (static).
type Day_Of_Month is range 1 .. 31;
type Day_Of_Month_Access is access all Day_Of_Month;
Access constant
Handles an access either to a constant or variable object which was created on any storage pool, on the stack or at library level (static), but with a restriction to read-only usage of the referenced object, whether it be intrinsically a constant or a variable.
type Day_Of_Month is range 1 .. 31;
type Day_Of_Month_Access is access constant Day_Of_Month;
Anonymous access
An anonymous access is used as a parameter to a function, procedure or a discriminated type. Here some examples:
procedure Test (Some_Day : access Day_Of_Month);
task type Thread (
Execute_For_Day : access Day_Of_Month)
is
-- ...In Ada 2005 a
end Thread;
type Day_Data (
Store_For_Day : access Day_Of_Month)
is record
-- components
end record;
Before you use an anonymous access you should consider if the "out" or "in out" modifier is not more appropriate - see access performance to see why.
This language feature will be made available in the forthcoming Ada 2005 standard.
In Ada 2005 an anonymous access will also be allowed as part of a record:
type Object is record
M : Integer;
Next : access Object;
end record;
Not null access
This language feature will be made available in the forthcoming Ada 2005 standard.
All access types can be modified with "not null":
type Day_Of_Month_Access is not null access Day_Of_Month;
The type must then always point to an object, so initializations are compulsory.
Constant anonymous access
This language feature will be made available in the forthcoming Ada 2005 standard.
An anonymous access to a constant object.
procedure Test (Some_Day : access constant Day_Of_Month);
Access to subprogram
An access to subprogram allows us to call a subprogram without knowing its name nor its declaration location. One of the uses of this kind of access is the well known callbacks.
type Callback_Procedure
is access procedure (
Id : Integer;
Text : String);
type Callback_Function
is access function (
The_Alarm : in Alarm)
return
Natural;
For getting an access to a subprogram the attribute Access is applied to a subprogram name with the proper prototype.
procedure Process_Event (
Id : Integer;
Text : String);
My_Callback : Callback_Procedure := ProcessEvent'Access;
Anonymous access to subprogram
This language feature will be made available in the forthcoming Ada 2005 standard.
procedure Test (
Call_Back : access procedure (
Id : Integer;
Text : String));
Using access types
Creating object in a storage pool
Objects in a storage pool are created with the keyword new:
Father : Person_Ref := new Person'(Father_First_Name, Father_Last_Name);
Deleting object from a storage pool
Although the Ada standard mentioned the use of a garbage collector which would automatically remove all unneeded objects that had been created on the heap (storage pool), only Ada compilers targeting a virtual machine like Java or .NET actually have garbage collectors.
Therefore in order to delete an object from the heap you will need the generic unit Ada.Unchecked_Deallocation.
with Ada.Unchecked_Deallocation;
procedure Deallocation_Sample is
type Vector is array (Integer range <>) of Float;
type Vector_Ref is access Vector;
procedure Free_Vector is new Ada.Unchecked_Deallocation
(Object => Vector, Name => Vector_Ref);
VA : Vector_Ref;
begin
VA := new Vector (1 .. 10);
VA.all := (others => 0.0);
-- ... Do whatever you need to do with the vector
Free_Vector (VA); -- The memory is deallocated and VA is now null
end Deallocation_Sample;
Since Ada does allow for user defined storage pools you could also try a garbage collector library.
Implicit dereferencing
If you declare a record type, and an access type for it, thus:
type Person is record
First_Name : String (1..30);
Last_Name : String (1..20);
end record;
type Person_Access is access Person;
you can use these types as follows:
Father : Person_Access := new Person'(Father_First_Name, Father_Last_Name);
...
Ada.Text_IO.Put(Father.all.First_Name);
However, .all is implicit if omitted, so we can write more concisely:
Ada.Text_IO.Put(Father.First_Name);
and be careful:
Obj1 : Person_Access := new Person'(...);
Obj2 : Person_Access := new Person'(...);
Obj1 := Obj2; -- Obj1 now refers to the same person as Obj2 (shallow copy)
Obj1.all := Obj2.all; -- Obj1 still refers to a different object from Obj2,
-- but it has the same content (deep copy).
Implicit dereferencing also applies to arrays:
type Vector is array (0..3) of Complex;
type Vector_Access is access Vector;
VA : Vector_Access := new Vector;
...
C : Complex := VA(3); -- a shorter equivalent for VA.all(3)
Access FAQ
A few "Frequently Asked Question" and "Frequently Encountered Problems" (mostly from former C users) regarding Ada's access types.
Access vs. access all
An access all can do anything a simple access can do. So one might ask: "Why use access at all?" - And indeed some programmers never use simple access.
But this is wrong because access all is more error prone! One example: When Unchecked_Deallocation is used on an access all it is not checked that the object actually belongs to the proper storage pool - or if the object belongs to any storage pool at all. The following example, invalidly and perhaps disastrously, will try to deallocate a stack object:
declare
type Day_Of_Month is range 1 .. 31;
type Day_Of_Month_Access is access all Day_Of_Month;
procedure Free
is new Ada.Unchecked_Deallocation (
Object => Day_Of_Month
Name => Day_Of_Month_Access);
A : aliased Day_Of_Month;
Ptr : Day_Of_Month_Access := A'Access;
begin
Free(Ptr);
end;
With a simple access you know at least that you won't try to deallocate a stack object.
Depending on the implementation an access might also render better performance then access all.
Access performance
Ada performs run-time checks on access types, so not all access types render the same performance. In other places of the Ada Programming we suggest that you should not care about runtime checks since the optimizer will remove them when they are not needed. However former C programmers often use anonymous access - which have worse performance - instead of of using "out" or "in out" which has best performance. Here a performance list - including the access modifiers - from best to worse:
- "in" modifier : parameter need only to be passed into the function.
- "out" modifier : parameter need only to be passed from the function.
- "in out" modifier : the compiler is free to use "call by value", "call by register" or "call by reference" and therefore best performance is to be expected.
- pool access : the access is always within a storage pool and only checks for not null are performed.
- access all : additional checks maybe needed.
- anonymous access : complex "stack deeps level" checks are needed so an "anonymous access" can be safely converted from and to an "access all" or "pool access".
Access vs. System.Address
An access is not a memory address. It is something more. For example, an "access to String" often needs some way of storing the string size as well. If you need a simple address and are not concerned about strong-typing, you may consider using the System.Address type.
C compatible pointer
The correct way to create a C compatible access is to use pragma Convention:
type Day_Of_Month is range 1 .. 31;
for Day_Of_Month'Size use Interfaces.C.int'Size;
pragma Convention (
Convention => C,
Entity => Day_Of_Month);
type Day_Of_Month_Access is access Day_Of_Month;
pragma Convention (
Convention => C,
Entity => Day_Of_Month_Access);
pragma Convention should be used on any type you want to use in C. The compiler should warn you if the type cannot be made C compatible.
You may also consider the following - shorter - alternative when declaring Day_Of_Month:
type Day_Of_Month is new Interfaces.C.int range 1 .. 31;
Before you use access types in C you should consider using the normal "in", "out" and "in out" modifiers. pragma Export and pragma Import knows how parameters are usually passed in C and will use a pointer to pass a parameter automatically where a "normal" C programmer would have used them as well.
Of course the definition of a "normal" C programmer is not left to change, the RM contains precise rules on when to use a pointer for "in", "out", and "in out" - see "B.3 Interfacing with C (http://www.adaic.com/standards/95lrm/html/RM-B-3.html) (Annotated (http://www.adaic.com/standards/95aarm/html/AA-B-3.html))".
Where is void*?
While actually been a problem for "interfacing with C", here is a possible solution:
procedure Test
is
subtype Pvoid is System.Address;
-- the declare in C, like this.
-- int C_fun(int *)
function C_fun(pv : Pvoid) return Integer;
pragma Import (C,C_fun,"C_fun");
Pointer : Pvoid ;
Input_Parameter : Integer := 32;
Return_Value : Integer;
begin
Pointer := Input_Parameter'Address;
Return_Value := C_fun(Pointer);
end Test;
Less portable but perhaps more usable (for 32 bit CPUs):
type void is mod 2 ** 32;
for void'Size use 32;
With GNAT you can get 32/64 bit portability by using:
type void is mod System.Memory_Size;
for void'Size use System.Word_Size;
See also
Wikibook
Ada Reference Manual
Ada 95
Ada 2005
- 3.7 Discriminants (http://www.adaic.com/standards/rm-amend/html/RM-3-7.html) (Annotated (http://www.adaic.com/standards/rm-amend/html/AA-3-7.html))
- 3.10 Access Types (http://www.adaic.com/standards/rm-amend/html/RM-3-10.html) (Annotated (http://www.adaic.com/standards/rm-amend/html/AA-3-10.html))
- 6.1 Subprogram Declarations (http://www.adaic.com/standards/rm-amend/html/RM-6-1.html) (Annotated (http://www.adaic.com/standards/rm-amend/html/AA-6-1.html))
- B.3 Interfacing with C (http://www.adaic.com/standards/rm-amend/html/RM-B-3.html) (Annotated (http://www.adaic.com/standards/rm-amend/html/AA-B-3.html))
Ada Quality and Style Guide
|