Archive-name: Ada programming pitfalls
Last-modified: 2003/7/18
Version: 0.2

This FAQ was compiled and written by Dale Stanbrough with numerous
contributions by others (typically from comp.lang.ada postings).
Acknowledgements are listed at end of this FAQ.

Copyright notice:

The Ada Programming Pitfalls Frequently Asked Questions is
distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY.  No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GNU General Public License for full details.

Everyone is granted permission to copy, modify and redistribute this
FAQ, but only under the conditions described in the GNU General Public
License.  Among other things, the copyright notice and this notice
must be preserved on all copies.

Where section authors are noted, the copyright is held by that author.
Where no author is noted, the copyright is held by the FAQ editor
Dale Stanbrough (dale@rmit.edu.au)

Changes, additions, comments, suggestions and questions to:
dale@rmit.edu.au

Wow! someone has seen this site, and made comments. I think this
is only the 2nd time this has happened!

  

Table of Contents:

   ==== PART 1 ====

S) 1.0 Introduction
 Q) 1.1  What does this FAQ cover?
 Q) 1.2  Where can I find the latest copy of this FAQ?
 
S) 2.0 Features with performance surprises
 Q) 2.1  Enumeration type rep specs
 Q) 2.2  Confirming Rep Specs
 Q) 2.3  Protected types on large systems
 Q) 2.4  Discriminants & Tagged types (extensions & finding components)
 Q) 2.5  Copying arrays (copy up or copy down?)

S) 3.0 Features likely to cause exceptions
 Q) 3.1  String indexes for function return values


S) 5.0 Acknowledgements
 Would you like to help? Please let me know of any pitfalls you may have
 stumbled over, and would like to let others know about.
================================================================================

S) 1.0 Introduction


Q) 1.1 What does this FAQ cover?

This FAQ has been created in response to a problem encountered by Joe Gwinn. It aims to distill the old lore, or rules of thumb, about issues in Ada that may be problematic/have unexpected costs in production code.

This is to help teams from falling into "beartraps", which can cause extensive grief totally out of proportion to the benefits of the feature being used.


Q) 1.2 Where can I find the latest copy of this FAQ?

For now until it settles down, I'll host it on

	http://www.cs.rmit.edu.au/~dale/ada/pitfalls/index.html


S) 2.0 Performance problems


Q) 2.1 Enumeration Rep Specs

Discussion:

An enumerated type can have an associated Representation Clause (often called a Rep Spec) which specifies the underlying values to be used for each item in the type. This is often used to match enumerated values with values obtained from either hardware or software (e.g. X11).

E.g.

	type Colours is (Red, Yellow, Green);
	for Colours'??? use (2#0001#, 2#0010#, 2#0100#);
However Colours'Pos (Green) still returns 2 (its value in the enumerated type, where counting starts at 0), not it's underlying representation. This can cause problems when the type is used as an index type in an array, a for loop, or when the 'Pred, 'Succ are used.

Solutions:

Translating b/w enums with & without rep specs
Don't use rep specs!


Q) 2.2 Confirming Rep Specs

Discussion

A Representation Clause that starts at zero, and assigns sequential numbers from 0 onwards (i.e. as the enumeration type would expected to be laid out by the compiler in the absence of a Rep. Clause) were often used in Ada83 code to ensure this behaviour (Ada83 enums didn't have to start at 0). These RC's are said to "confirm" the standard representation. Ada95 compilers, which _will_ use 0 based representations, may see the clause and "kick in" the special enum <-> representation software, and cause unneeded slowdowns.

Solution

Either remove the RC, or tell your compiler vendor to special case this situation.

Related Postings

Gnat


Q) 2.3 Protected types on large systems

Discussion:

The use of protected types on some systems (I think it is where there is a protected O/S running) combined with mandatory priority ceiling inheritance, can cause expensive locking protocols to be required.

Solution:

?

Related Posts:

?


Q) 2.4 Unconstrained types

Discussion:

Unconstrained types require the run time overhead of a descriptor which lists the start address of the array, the 'first and 'last value of the array. This can cause significant overhead when accessing components, combined with array bound checking.

Some compilers (e.g. Gnat) provide for virtual addresses, it stores the address of where the 0th element _would_ be, even if the array starts at index 25 (for example).

Q) 2.5 Copying arrays (copy up or copy down?)

Discussion:

Copying an array onto itself is guarenteed to work in Ada. However when the bounds can't be determined a-priori, the copying direction has to be determined at run time. e.g.

    procedure Move (Item : in out String; From, To : in Positive) is
    begin
       Item (To .. To + 4) := Item (From .. From + 4);
    end Move;
    
    ...
    Move (Some_String, From => 1, To => 2);
    Move (Some_String, From => 2, To => 1);
Here the program has to determine at run time how to process the string assignment.

Solution:

None


S) 3.0 Features likely to cause exceptions

Q) 3.1 String indexes for function return values

Discussion:

A string (or any unconstrained array type) returned from a function retains the bounds it was given. An attempt to access the return string with an assumption that the values start at 1 can lead to exceptions.

E.g.

	function Slice (Item : String; From : Positive; To : Natural) return String is
	begin
	   return Item (From..To);
	end;
	
	...
	Substring : constant String := Slice ("hello there!", 7, 11);
 begin
    if Substring (1) = 't' then... -- exception, Substring has range 7..11

Solution:

Create a subtype within the function, and slide the values back into an appropriate index value.

E.g.
	function Slice (Item : String; From : Positive; To : Natural) return String is
	begin
	   declare
	      subtype Slide is String (1..To - From + 1);
	   begin
	      return Slide (Item (From..To));
	   end;
	end;