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 (firstname.lastname@example.org) Changes, additions, comments, suggestions and questions to: email@example.com 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
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.
For now until it settles down, I'll host it on
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).
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.
Translating b/w enums with & without rep specs
Don't use rep specs!
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.
Either remove the RC, or tell your compiler vendor to special case this situation.
Q) 2.3 Protected types on large systems
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.
Q) 2.4 Unconstrained types
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?)
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.
Q) 3.1 String indexes for function return values
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.
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
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;