Ada 95 Quality and Style Guide Chapter 5

Chapter 5: Programming Practices - TOC - 5.9 ERRONEOUS EXECUTION AND BOUNDED ERRORS

5.9.6 Initialization


  • Initialize all objects prior to use.
  • Use caution when initializing access values.
  • Do not depend on default initialization that is not part of the language.
  • Derive from a controlled type and override the primitive procedure to ensure automatic initialization.
  • Ensure elaboration of an entity before using it.
  • Use function calls in declarations cautiously.

  • example

    The first example illustrates the potential problem with initializing access values:

    procedure Mix_Letters (Of_String : in out String) is
       type String_Ptr is access String;
       Ptr : String_Ptr := new String'(Of_String);  -- could raise Storage_Error in caller
    begin -- Mix_Letters
       ...  -- cannot trap Storage_Error raised during elaboration of Ptr declaration
    end Mix_Letters;

    The second example illustrates the issue of ensuring the elaboration of an entity before its use:

    package Robot_Controller is
       function Sense return Position;
    end Robot_Controller;
    package body Robot_Controller is
       Goal : Position := Sense;       -- This raises Program_Error
       function Sense return Position is
       end Sense;
    begin  -- Robot_Controller
       Goal := Sense;                  -- The function has been elaborated.
    end Robot_Controller;


    Ada does not define an initial default value for objects of any type other than access types, whose initial default value is null. If you are initializing an access value at the point at which it is declared and the allocation raises the exception Storage_Error, the exception is raised in the calling not the called procedure. The caller is unprepared to handle this exception because it knows nothing about the problem-causing allocation.

    Operating systems differ in what they do when they allocate a page in memory: one operating system may zero out the entire page; a second may do nothing. Therefore, using the value of an object before it has been assigned a value causes unpredictable (but bounded) behavior, possibly raising an exception. Objects can be initialized implicitly by declaration or explicitly by assignment statements. Initialization at the point of declaration is safest as well as easiest for maintainers. You can also specify default values for components of records as part of the type declarations for those records.

    Ensuring initialization does not imply initialization at the declaration. In the example above, Goal must be initialized via a function call. This cannot occur at the declaration because the function Sense has not yet been elaborated, but it can occur later as part of the sequence of statements of the body of the enclosing package.

    An unelaborated function called within a declaration (initialization) raises the exception, Program_Error, that must be handled outside of the unit containing the declarations. This is true for any exception the function raises even if it has been elaborated.

    If an exception is raised by a function call in a declaration, it is not handled in that immediate scope. It is raised to the enclosing scope. This can be controlled by nesting blocks.

    See also Guideline 9.2.3.


    Sometimes, elaboration order can be dictated with pragma Elaborate_All. Pragma Elaborate_All applied to a library unit causes the elaboration of the transitive closure of the unit and its dependents. In other words, all bodies of library units reachable from this library unit's body are elaborated, preventing an access-before-elaboration error (Rationale 1995, §10.3). Use the pragma Elaborate_Body when you want the body of a package to be elaborated immediately after its declaration.

    < Previous Page Search Contents Index Next Page >
    1 2 3 4 5 6 7 8 9 10 11
    Appendix References Bibliography