Similar presentations

1
Currie Colket The MITRE Corporation Phone: (703) 883-7381 Email: colket@mitre.org | colket@acm.org SIGAda 2001 1 October 2001 SIGAda Home Page  http://www.acm.org/sigada Acknowledgement and Thanks to Bill Thomas and Bill Bail for their help and ideas. What You Always Wanted to Know About Exceptions But Were Afraid to “Raise”

5
5 Introduction Ada Exceptions l Exceptions are - Declared, like types, variables, etc.; there are also some predefined exceptions - Raised, explicitly (by a raise statement) or implicitly (by Ada runtime) - Caught, explicitly (by name) or implicitly ("when others =>") - Propagated, from called subprogram to calling subprogram l In general, exceptions are an excellent feature - Reliability enhancing feature designed to help specify program behavior in the presence of unexpected events - Allows separation of error-handling code from normal code l However, good design and coding guidelines are essential - Cannot infer from a subprogram specification what exceptions the subprogram may propagate l And automated checking for conformance to guidelines is beneficial

7
7 Benefits of Using Ada Exceptions l Provides a reliability-enhancing language feature designed to help specify program behavior in the presence of errors or unexpected events l Supports the logical differentiation of normal and exceptional control paths, which can lead to clarity and ease of understanding l Avoids "overloading" a parameter with multiple layers of abstraction (i.e., products of computation and status of that computation), which can cause confusion l Supports the notion of error status that should not be ignored (a notorious practice in, e.g., much C software) l Intuitive way of dealing with results of interactions among asynchronous independent activities - No amount of precondition testing can avoid chance of encountering error condition (e.g., jammed cable) l Supports the return to some known safe state

13
13 Ada 95 RM 11.2 Exception Handlers - 4 l When an exception occurrence is raised by the execution of a given construct, the rest of the execution of that construct is abandoned; i.e., Control is transferred to the handler. Then: l If the construct is the sequence_of_statements of a handled_sequence_of_statements that has a handler with a choice covering the exception, the occurrence is handled by that handler; l If the construct is a task_body or main program, the exception does not propagate further; The task dies; ditto for main program. l Otherwise, the occurrence is propagated to the innermost dynamically enclosing execution, i.e., the occurrence is raised again in that context. Handler replaces abandoned portion of handled_sequence_of_statements

18
18 Ada 95 RM 11.5 Suppressing Checks - 1 pragma Suppress gives permission to an implementation to omit certain language-defined checks pragma Suppress(identifier [, [On =>] name]); l Allowed only immediately within a declarative_part, immediately within a package_specification, or as a configuration pragma. l For use within a package_specification, the name shall denote an entity (or several overloaded subprograms) declared immediately within the package_specification. If a given check has been suppressed, and the corresponding error situation occurs, the execution of the program is erroneous.

20
20 Ada 95 RM 11.6 Exceptions and Optimization (The fine print) The following additional permissions are granted to the implementation: l An implementation need not always raise an exception when a language-defined check fails. Instead, the operation that failed the check can simply yield an undefined result. The exception need be raised by the implementation only if, in the absence of raising it, the value of this undefined result would have some effect on the external interactions of the program. In determining this, the implementation shall not presume that an undefined result has a value that belongs to its subtype, nor even to the base range of its type, if scalar. Having removed the raise of the exception, the canonical semantics will in general allow the implementation to omit the code for the check, and some or all of the operation itself. l If an exception is raised due to the failure of a language-defined check, then upon reaching the corresponding exception_handler (or the termination of the task, if none), the external interactions that have occurred need reflect only that the exception was raised somewhere within the execution of the sequence_of_statements with the handler (or the task_body), possibly earlier (or later if the interactions are independent of the result of the checked operation) than that defined by the canonical semantics, but not within the execution of some abort-deferred operation or independent subprogram that does not dynamically enclose the execution of the construct whose check failed. An independent subprogram is one that is defined outside the library unit containing the construct whose check failed, and has no Inline pragma applied to it. Any assignment that occurred outside of such abort-deferred operations or independent subprograms can be disrupted by the raising of the exception, causing the object or its parts to become abnormal, and certain subsequent uses of the object to be erroneous, as explained in 13.9.1. l The permissions granted by this clause can have an effect on the semantics of a program only if the program fails a language-defined check.

22
22 Design Considerations Thoughts on Exception Use Impacting Design l Unhandled exceptions will propagate all the way up the calling sequence, causing termination of the task or program l Exception propagation can violate abstractions, forcing clients of abstractions to handle implementation details l Anonymous exceptions can result from the interaction of exception propagation (dynamic) with Ada scoping rules (static) l Analysis of exception propagation can be difficult in large systems due to the mixture of dynamic and static aspects l Subtle interactions with other language features, e.g., propagation can be arbitrarily delayed waiting on termination of dependent tasks in a frame, propagation can expose parameter-passing mechanisms, etc. Proper Design Can Result in Highly Effective Results

24
24 Ada 95 Quality & Style Guide – Section 3.2.7 Naming Conventions for Exceptions Guideline: l Use a name that indicates the kind of problem the exception represents. Example: Invalid_Name: exception; Stack_Overflow: exception; Rationale: l Naming exceptions according to the kind of problem they are detecting enhances the readability of the code.

25
25 Ada 95 Quality & Style Guide – Section 3.3.2 File Headers for Exceptions Guideline: l Describe the complete interface to the program unit, including any exceptions it can raise and any global effects it can have. Example: -- Exceptions: -- Node_Not_Defined – A node must be defined … Rationale: l The purpose of a header comment on the specification of a program unit is to help the user understand how to use the program unit. l None of this information can be determined from the Ada specification of the program unit.

26
26 Ada 95 Quality & Style Guide – Section 3.3.5 Comments for Exceptions Guideline: l Comment on all data types, objects, and exceptions unless their names are self-explanatory. - The conditions under which an exception is raised should be commented. Example: Node_Already_Defined : exception; --| Raised when an attempt is made to define --| a node with an identifier which already --| defines a node. Rationale: l The reader has no other way to find out the exact meaning of the exception (without reading the code in the package body).

27
27 Ada 95 Quality & Style Guide – Section 4.3.1 Using Exceptions to Help Define an Abstraction - 1 Guidelines: l For unavoidable internal errors for which no user recovery is possible, declare a single user-visible exception. Inside the abstraction, provide a way to distinguish between the different internal errors. l Do not borrow an exception name from another context. l Export (declare visibly to the user) the names of all exceptions that can be raised. l In a package, document which exceptions can be raised by each subprogram and task entry. l Do not raise exceptions for internal errors that can be avoided or corrected within the unit. l Do not raise the same exception to report different kinds of errors that are distinguishable by the user of the unit.

28
28 Ada 95 Quality & Style Guide – Section 4.3.1 Using Exceptions to Help Define an Abstraction - 2 Guidelines (continued): l Provide interrogative functions that allow the user of a unit to avoid causing exceptions to be raised. l When possible, avoid changing state information in a unit before raising an exception. l Catch and convert or handle all predefined and compiler- defined exceptions at the earliest opportunity. l Do not explicitly raise predefined or implementation-defined exceptions. l Never let an exception propagate beyond its scope.

30
30 Ada 95 Quality & Style Guide – Section 5.4.5 Data Structures – Dynamic Data Guideline: l Provide handlers for Storage_Error. Example: when Storage_Error => Do_Some_Garbage_Collection; raise; -- Allowing subprogram to be called again in loop. Rationale: l Prepare handlers for the exception Storage_Error, and consider carefully what alternatives you may be able to include in the program for each such situation.

31
31 Ada 95 Quality & Style Guide – Section 5.6.9 Statements – Blocks Guideline: l Use blocks to define local exception handlers. Example: for I in 1.. Sample_Limit loop Get_Samples_And_Ignore_Invalid_Data: declare -- declarations begin Get_Value(Current); exception when Constraint_Error => null; -- Continue trying when Accelerometer_Device.Failure => raise Accelerometer_Device_Failed; end Get_Samples_And_Ignore_Invalid_Data; exit when Current <= 0.0; -- Slowing down end loop; Rationale: Local exception handlers can catch exceptions close to the point of origin and allow them to be either handled, propagated, or converted.

32
32 Ada 95 Quality & Style Guide – Section 5.8 Using Exceptions – Programming Practices “Ada exceptions are a reliability-enhancing language feature designed to help specify program behavior in the presence of errors or unexpected events. “Exceptions are not intended to provide a general purpose control construct.” “Further, liberal use of exceptions should not be considered sufficient for providing full software fault tolerance (Melliar- Smith and Randell 1987).” Sections => 5.8.1 Handling Versus Avoiding Exceptions 5.8.2 Handlers for Others 5.8.3 Propagation 5.8.4 Localizing the Cause of an Exception

33
33 Ada 95 Quality & Style Guide – Section 5.8.1 Handling Versus Avoiding Exceptions - 1 Guidelines: l When it is easy and efficient to do so, avoid causing exceptions to be raised. l Provide handlers for exceptions that cannot be avoided. l Use exception handlers to enhance readability by separating fault handling from normal execution. Do not use exceptions and exception handlers as goto statements. l Do not evaluate the value of an object (or a part of an object) that has become abnormal because of the failure of a language-defined check.

34
34 Ada 95 Quality & Style Guide – Section 5.8.1 Handling Versus Avoiding Exceptions - 2 Example: l Test an integer for 0 before dividing by it l Call an interrogative function Stack_Is_Empty before invoking the pop procedure of a stack package l Use exceptions where such a - test is too expensive [Entry_Exists before each call to the procedure Modify_Entry simply to avoid raising the exception Entry_Not_Found] or - or too unreliable [Concurrent Operations] Rationale: l In many cases, it is possible to detect easily and efficiently that an operation you are about to perform would raise an exception. l When fault handling and only fault handling code is included in exception handlers, the separation makes the code easier to read.

35
35 Ada 95 Quality & Style Guide – Section 5.8.2 Handlers for Others - 1 Guidelines: l When writing an exception handler for when others, capture and return additional information about the exception through the Exception_Name, Exception_Message, or Exception_Information subprograms declared in the predefined package Ada.Exceptions. l Use others only to catch exceptions you cannot enumerate explicitly, preferably only to flag a potential abort. l During development, trap others, capture the exception being handled, and consider adding an explicit handler for that exception. Rationale: l Writing a handler without these subprograms limits the amount of error information you may see. l Programming a handler for others requires caution. You should name the exception in the handler.

37
37 Ada 95 Quality & Style Guide – Section 5.8.3 Propagation Guidelines: l Handle all exceptions, both user and predefined. l For every exception that might be raised, provide a handler in suitable frames to protect against undesired propagation outside the abstraction. Rationale: l The statement that “it can never happen” is not an acceptable programming approach. l You must assume it can happen and be in control when it does. You should provide defensive code routines for the “cannot get here” conditions. l You should catch the exception and propagate it or a substitute only if your handler is at the wrong abstraction level to effect recovery.

38
38 Ada 95 Quality & Style Guide – Section 5.8.4 Localizing the Cause of an Exception Guidelines: l Do not rely on being able to identify the fault-raising, predefined, or implementation-defined exceptions. l Use the facilities defined in Ada.Exceptions to capture as much information as possible about an exception. l Use blocks to associate localized sections of code with their own exception handlers. Rationale: l In an exception handler, it is very difficult to determine exactly which statement and which operation within that statement raised an exception. l The predefined exceptions are candidates for conversion and propagation to higher abstraction levels for handling there. l User-defined exceptions, being more closely associated with the application, are better candidates for recovery within handlers.

39
39 Ada 95 Quality & Style Guide – Section 5.9.5 Suppression of Exception Check Section 5.9 is: ERRONEOUS EXECUTION AND BOUNDED ERRORS Guidelines: l Do not suppress exception checks during development. l Minimize suppression of exception checks during operation. l If necessary, during operation, introduce blocks that encompass the smallest range of statements that can safely have exception checking removed. Rationale: l If you disable exception checks and program execution results in a condition in which an exception would otherwise occur, the program execution is erroneous. The results are unpredictable. l Further, you must still be prepared to deal with the suppressed exceptions if they are raised in and propagated from the bodies of subprograms, tasks, and packages you call. l By minimizing the code that has exception checking removed, you increase the reliability of the program.

40
40 Ada 95 Quality & Style Guide – Section 5.9.8 Exception Propagation Section 5.9 is: ERRONEOUS EXECUTION AND BOUNDED ERRORS Guideline: l Prevent exceptions from propagating outside any user- defined Finalize or Adjust procedure by providing handlers for all predefined and user-defined exceptions at the end of each procedure. Rationale: l Using Finalize or Adjust to propagate an exception results in a bounded error (Ada Reference Manual 1995, §7.6.1). Either the exception will be ignored or a Program_Error exception will be raised. [For Controlled Types - See RM §7.6 for Ada.Finalization]

42
42 Ada 95 Quality & Style Guide – Section 6.2.2 Concurrency – Defensive Task Communications - 2 Rationale: l The exception Program_Error is raised if a selective accept statement is reached, all of whose alternatives are closed (i.e., the guards evaluate to False and there are no alternatives without guards), unless there is an else part. When all alternatives are closed, the task can never again progress, so there is by definition an error in its programming. l Because an else part cannot have a guard, it can never be closed off as an alternative action; thus, its presence prevents Program_Error. However, an else part, a delay alternative, and a terminate alternative are all mutually exclusive, so you will not always be able to provide an else part.

43
43 Ada 95 Quality & Style Guide – Section 6.2.2 Concurrency – Defensive Task Communications - 3 Rationale (continued): l The exception Tasking_Error can be raised in the calling task whenever it attempts to communicate. There are many situations permitting this. Few of them are preventable by the calling task. l If an exception is raised during a rendezvous and not handled in the accept statement, it is propagated to both tasks and must be handled in two places. l The handling of the others exception can be used to avoid propagating unexpected exceptions to callers (when this is the desired effect) and to localize the logic for dealing with unexpected exceptions in the rendezvous. After handling, an unknown exception should normally be raised again because the final decision of how to deal with it might need to be made at the outermost scope of the task body.

44
44 Ada 95 Quality & Style Guide – Section 6.3.1 Avoiding Undesired Task Termination - 1 Guideline: l Consider using an exception handler for a rendezvous within the main loop inside each task. Rationale: l Allowing a task to terminate might not support the requirements of the system. Without an exception handler for the rendezvous within the main task loop, the functions of the task might not be performed. l The use of an exception handler is the only way to guarantee recovery from an entry call to an abnormal task. Use of the 'Terminated attribute to test a task’s availability before making the entry call can introduce a race condition where the tested task fails after the test but before the entry call.

46
46 Ada 95 Quality & Style Guide – Section 6.3.4 Abnormal Task Termination - 1 Guidelines: l Place an exception handler for others at the end of a task body. l Consider having each exception handler at the end of a task body report the task’s demise. l Do not rely on the task status to determine whether a rendezvous can be made with the task. Rationale: l A task will terminate if an exception is raised within it for which it has no handler. In such a case, the exception is not propagated outside of the task (unless it occurs during a rendezvous). The task simply dies with no notification to other tasks in the program. Therefore, providing exception handler for others, ensures that a task can regain control after an exception occurs.

48
48 Ada 95 Quality & Style Guide – Section 7.1 Portability - Ada 83 Obsolescent Features Guideline: l Avoid using the exception Numeric_Error Rationale: l Ten years of reflection on the use of Ada 83 led to the conclusion that some features of the original language are not as useful as originally intended. l It would have been desirable to remove the obsolescent features completely, but that would have prevented the upward compatible transition from Ada 83 to Ada 95. l Thus, the obsolescent features remain in the language and are explicitly labeled as such in Annex J of the Ada Reference Manual (1995). The features listed in Annex J are candidates for removal from the language during its next revision.

49
49 Ada 95 Quality & Style Guide – Section 7.5 Portability - Exceptions Guidelines: l Do not depend on the exact locations at which predefined exceptions are raised. l Do not rely on the behavior of Ada.Exceptions beyond the minimum defined in the language. l Do not raise implementation-specific exceptions. l Convert implementation-specific exceptions within interface packages to visible user-defined exceptions. Rationale: l Predefined exceptions may be raised from different locations. Predefined exceptions are associated with a variety of conditions. l No exception defined specifically by an implementation can be guaranteed to be portable to other implementations. Do not allow yourself to be forced to find and change the name of every handler you have written for these exceptions when the program is ported.

50
50 Ada 95 Quality & Style Guide – Section 8.2.7 Reusability - Exceptions Guideline: l Propagate exceptions out of reusable parts. Handle exceptions within reusable parts only when you are certain that the handling is appropriate in all circumstances. l Propagate exceptions raised by generic formal subprograms after performing any cleanup necessary to the correct operation of future invocations of the generic instantiation. l Leave state variables in a valid state when raising an exception. l Leave parameters unmodified when raising an exception. Rationale: l When an exception is raised by a generic formal subprogram, the generic unit is in no position to understand why or to know what corrective action to take. l The generic unit must first clean up after itself, restoring its internal data structures to a correct state so that future calls may be made to it after the caller has dealt with the current exception.

51
51 Design Considerations Example 1: System Example System Control Navigation Sensor Control TrackingComm RadarInfra RedESMAcoustics... What do we do if exception raised Here? Or Here? Where handled? Same Strategy across system? What is approach for tasking and protected objects? What are repercussions? Is critical data protected? How reported? Are there differences between test & production? What is criticality of error? Any Operator decisions?

52
52 Design Considerations Example 2: ASIS Client - Server Example l The Ada Semantic Interface Specification (ASIS) exception handling mechanism is a good example demonstrating the types of things useful to do in a design. The Ada Semantic Interface Specification (ASIS) is an interface between an Ada environment (as defined by ISO/IEC 8652:1995) and any tool or application requiring information from it. An Ada environment includes valuable semantic and syntactic information. ASIS is an open and published callable interface which gives CASE tool and application developers access to this information. ASIS has been designed to be independent of underlying Ada environment implementations, thus supporting portability of software engineering tools while relieving tool developers from needing to understand the complexities of an Ada environment's proprietary internal representation. In short, ASIS can provide the foundation for your code analysis activities.

53
53 What is ASIS? Ada Source Code CompileLink Provides Syntactic and Semantic Information from Ada Environment using a standard interface A P L I C A T I O N SYSTEMSYSTEM

59
59 Design Considerations - Example ASIS Exceptions used with ASIS Errors l ASIS reports all operational errors by raising an exception. l Whenever an ASIS implementation raises one of the exceptions declared in package Asis.Exceptions, it will previously have set the values returned by the Status and Diagnosis queries to indicate the cause of the error. l The possible values for Status are indicated in the definition of Error_Kinds, with suggestions for the associated contents of the Diagnosis string as a comment. l The Diagnosis and Status queries are provided in the Asis.Implementation package to supply more information about the reasons for raising any exception. l ASIS applications are encouraged to follow this same convention whenever they explicitly raise any ASIS exception--always record a Status and Diagnosis prior to raising the exception.

64
64 Exception Gotchas - 1 Function Handlers Must Raise Exception or Return l Functions must either return a value or propagate an exception. Otherwise the exception Program_Error is raised. Six instances were detected where an exception handler would handle exceptions raised, but would neither return a known safe value or propagate an exception. The fact that the designer added the exception handler implied that exceptions were possible. function Next_Packet return Rcv_Type is... begin... exception when Exception_Id: others => Log_Error (Package_Id & ".Next_Packet: Unhandled exception: " & Ada.Exceptions.Exception_Information (Exception_Id)); end Next_Packet; 6 Violations in recent analysis

65
65 Exception Gotchas - 2 Unset Out Parameters l When a handler does not propagate the exception, out parameters of a procedure and return values of functions should be set. In the case of a procedure, if the out parameters are not set appropriately, the calling program is likely to use them erroneously. function Compute_Range return Integer is... begin... exception when Range_Not_Computable => return 0; when others => Log_Error (Package_Id & ".Next_Packet: Unhandled exception: " & Ada.Exceptions.Exception_Information (Exception_Id)); raise; end Next_Packet; Acceptable return value Acceptable to reraise the exception Either prevents Program_Error

66
66 Exception Gotchas - 3 Missing Storage Error Handler For Allocators l Any allocator can exhaust the available space for the collection, the use of allocators should be limited and the "out of memory" case handled locally. An exception handler for Storage Error should be provided in the local scope for each allocator. 143 Violations in recent analysis

67
67 Exception Gotchas - 4 Exception handler with "when others => null " l Use of a "when others" whose statement body is "null" may be inappropriate in that they catch all exceptions but provide no further processing of conditions that led to the exception. l Exceptions should be used to trap expected problems and revert to some known safe state. These are normally classified as serious errors since should an exception be raised, processing continues which is likely degraded. when others => null; Catches the exception, but erroneous problem is not resolved, resulting in erroneous execution, which some folks call “Graceful Degradation” 13 Violations in recent analysis

68
68 Exception Gotchas - 5 Use of When Others in an Exception Handler l Such handlers are a catchall and may be inappropriate in some cases. It prevents the opportunity to return the system to a known safe state based on the exception named. Typical action is to log the exception and to allow the system to perform in a degraded state. It is better practice to handle all potential exceptions explicitly. It should be noted that it is quite valuable to have such an exception handler within a looped block for tasks and main programs, as the absence there can result in a system crash. when Exception_Id: others => Log_Error (Package_Id & ".Next_Packet: Unhandled exception: " & Ada.Exceptions.Exception_Information (Exception_Id)); Logs the exception, but erroneous problem is not resolved allowing for “Graceful Degradation” 659 Violations in recent analysis

69
69 Exception Gotchas - 6 Raised Exceptions Non Propagating l Explicit raising of exceptions that are caught in the local scope is similar in nature to a Goto statement. Use of exceptions in this manner represents another form of an unstructured program jump. It makes programs harder to understand, test, and modify. l If the problem can be resolved at the local level, perhaps the use of exceptions is the wrong abstraction. 7 Violations in recent analysis

70
70 Exception Gotchas - 7 Raise Predefined Exceptions l Raising predefined exceptions adds confusion as to the source of the exception. The declaration of application exceptions keeps system run-time errors and application errors separate. This is considered to be a poor programming practice. Raise Constraint_Error; 8 Violations in recent analysis all for Constraint_Error

71
71 Exception Gotchas - 8 Non-Visible Exception Declarations l This is the declaration of an exception in a non-visible part of the program. Non-visible declarations can be very dangerous as they can be only handled within the scope of the declaration (except with a when others). Unintended propagation outside this scope may impact remote sections of the code and be a difficult error to find. 11 Violations in recent analysis package QUEUE is procedure DEQUEUE (Object : out Object_type); procedure ENQUEUE (Object : in Object_type); function Is_Empty return Boolean; function Is_Full return Boolean; end QUEUE; and in body: OVERFLOW, UNDERFLOW : exception; Declarations of exceptions in body is not useful for desired abstractions

72
72 Exception Gotchas - 9 Exceptions that Propagate Out of Visible Scope of Subprogram l Subprograms should not raise exceptions that are outside the visible scope of calling programs. This creates a serious problem where the exception cannot be handled by name to take the appropriate action for the raised exception. The raised exception can only be handled by a "when others =>" option which cannot distinguish which exception has been raised. procedure Erroneous_Propagation_Demo is My_Exception: exception; begin... raise My_Exception; exception when My_Exception => raise; end Erroneous_Propagation_Demo; 4 Violations in recent analysis Propagates Outside of Scope

73
73 Workshop on Exception Handling for a 21st Century Programming Language May 14, 2001, Leuven, Belgium Future of Ada Exceptions - 1 The aims of the workshop were: l To share experience on how to build modern systems that have to deal with abnormal situations; l To discuss how solutions to those needs can be developed employing standard Ada features including the current exception handling paradigm; and l To propose new exception handling mechanisms / paradigms that can be included in future revisions of the Ada language and also fit high integrity language profiles for safety critical systems.

74
74 Future of Ada Exceptions - 2 Some of the issues addressed at Workshop: l Exception handling model remains based on Ada 83 while Ada 95 is object oriented. l Exceptions and concurrency are not well integrated - Task with an unhandled exception dies silently - Asynchronous transfer of control for passing exceptions asynchronously between tasks l New fault tolerance schemes based on existing exception handling facilities have been developed in research environments - Higher level abstractions providing more advanced mechanisms

75
75 Future of Ada Exceptions - 3 Ideas Emerged: l Extensions to Exception Handling should be downward compatible with Ada95 l Exceptions can be (generic) parameters l Unhandled Exceptions must be declared in the subprogram header (signature) l Exceptions are types l It should be possible to know if (for a controlled type) “Finalize” is called with a pending exception l Visibility Control should be controlled l There should be some notification mechanism for tasks that complete by raising an exception l And as a study topic: Instead of associating exceptions with subprograms, it would be nice to be able to associate exceptions with classes, types, objects, etc.

77
77 Conclusion l Ada 95 Exceptions can be effective in supporting situations that might otherwise result in erroneous execution. l Handled exceptions can be used to return the system to some known safe state or to propagate the exception to a handler that can return the system to some known safe state. l The Ada.Exceptions package provides excellent support to help debug a program. If you are not currently using it, plan to use it. l Exceptions must be used intelligently as improper use can result in serious errors including Program_Error. l Code Analysis Tools can be essential. l There are likely to be enhancements to exceptions for Ada 0X.