home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 17
- EXCEPTIONS
-
-
- EXCEPTIONS ARE NOT NEW TO YOU
- _________________________________________________________________
-
- Assuming you have completed part 1 of this tutorial, you have seen
- many references to exceptions, but we have said little about how
- you can use them. The purpose of this chapter is to instruct you
- on the use of exceptions, and by the time you complete it, you will
- have the ability to use exceptions to develop a program with its
- own error handling ability.
-
-
- WHY DO WE NEED EXCEPTIONS?
- _________________________________________________________________
-
- The original charter for the development of Ada included the
- ability to operate in a real-time environment. You already
- understand, if you have much programming experience, that if it is
- possible for an error to surface, it will eventually surface. Many
- programming languages simply terminate operation if a "fatal error"
- is detected, but this could be a disaster if the program was
- controlling a real-time system upon which human lives or safety
- depended. A 747 in final approach to the airport, or a system used
- in a hospital operating room would be two such examples of systems
- that simply could not be terminated abruptly because a bad data
- point was somehow accumulated. The careful application of Ada
- exceptions will allow the software to gracefully recover from such
- a situation rather than aborting operation completely.
-
-
- OUR FIRST EXCEPTION
- _________________________________________________________________
-
- Examine the program named EXCEPT1.ADA for our ===============
- first example program with an exception handler. EXCEPT1.ADA
- Ignore lines 21 and 22 for the moment and you ===============
- will have a program that is not at all unusual,
- and should pose no problem for you to
- understand. The program does have a carefully introduced error
- however, because when we reach a value of 4 for Index in line 17,
- we will be attempting to divide by zero. Dividing by zero is not
- allowed in any programming language, because the answer is infinite
- and therefore undefined. The Ada runtime system will, by
- definition, cause the exception named Numeric_Error to be raised,
- which is the Ada way of saying that a divide by zero was attempted.
- This signals the system to do something about it. (Actually, there
- are many other ways to get the Numeric_Error exception raised but
- we will worry about them later.)
-
-
-
- Page 17-1
-
- Chapter 17 - Exceptions
-
- The Ada system will search, in a very definite way, for any
- instructions we have given about this error, and if it finds none,
- will terminate operation of the program after issuing a message
- concerning the error. If we have given instructions about what to
- do with the error, it will execute the instructions and continue
- operation as we direct it to do. The method of giving the system
- these instructions is illustrated in lines 21 and 22.
-
-
- HOW ARE EXCEPTIONS HANDLED?
- _________________________________________________________________
-
- When any exception is raised, the system immediately looks at the
- end of the current block or subprogram for the reserved word
- exception. If it is found, and if the specific exception that was
- raised is defined there, the instructions associated with that
- exception are executed, and the subprogram or block is exited.
-
- To define a handler for a specific exception, the reserved word
- when is used, followed by the name of the exception, and finally
- the sequence of statements to be executed following the =>
- operator. The sequence of statements can be of arbitrary
- complexity, but should be kept simple due to the nature of
- exception handling. In this case, we output a message to the
- monitor and do nothing else. As many different exceptions as
- desired can be handled at the end of any block or subprogram by
- adding additional constructs of the form,
-
- when <exception_name> => instructions;
-
- following the single instance of the reserved word exception. We
- will study examples of multiple exception handlers later in this
- chapter.
-
-
-
- WHAT HAPPENS FOLLOWING EXCEPTION HANDLING?
- _________________________________________________________________
-
- Following handling of the exception, the program executes an
- otherwise normal return to the calling program, and the normal
- sequence of instructions in the calling program is executed. Note
- that it is impossible to jump back into the subprogram or block in
- which the exception was raised from the exception handling routine
- at the end of that block. In this case, because of the logic used,
- the loop defined in line 13 is terminated early because we
- essentially jumped out of the loop and the program is ended. If
- an exception handler or a group of exception handlers is included,
- it must be the last thing in the block. If normal execution of the
- block reaches the end of the executable statements by coming to the
- reserved word exception, the block is terminated normally. You
- cannot drop into the exception handler at the end of a block. The
- only way to get to the exception handling code is through raising
- an exception.
-
- Page 17-2
-
- Chapter 17 - Exceptions
-
-
- In spite of the additional questions you have at this point,
- compile and execute this program. Observe the results, and if you
- do not understand the output, reread the above text until you do,
- because these fundamental points are essential to understanding the
- entire topic of exceptions.
-
-
-
- LET'S USE SEVERAL EXCEPTIONS
- _________________________________________________________________
-
- Examine the program named EXCEPT2.ADA for ===============
- additional examples of exceptions. This program EXCEPT2.ADA
- will answer many of your questions about ===============
- exceptions.
-
- The portion of the program defined in lines 46 through 50, along
- with its associated procedure is logically identical to the last
- example program except for the loop being moved to the calling
- program. When the divide by zero is detected by the system, which
- raises the Numeric_Error exception, the exception is handled by the
- exception handler defined in lines 20 and 21, and the return to the
- calling program is effected. In this case however, when control
- returns to the calling program, we are still inside of the loop,
- and the loop completes normally. This should indicate to you that
- by careful selection of where you handle exceptions, you can
- control the overall result. We will see more about this as we
- continue our study of exceptions.
-
- The logic of the second group of instructions, found in lines 52
- through 67, is identical to the logic of the first group as studied
- in the last paragraph. The only difference is that the procedure
- has been changed into a block and inserted into the code in an
- inline fashion. This has been done to illustrate the use of an
- exception in a block of code, and to illustrate that the exception
- handler for the block of code is put at the end of that block.
- After the exception is raised and handled, execution begins at the
- first statement following the block. Because the block is
- contained within the loop, the exception is handled within the loop
- and the loop runs to completion.
-
-
-
- MULTIPLE EXCEPTION HANDLERS
- _________________________________________________________________
-
- Finally, we come to the section of code in lines 69 through 72,
- consisting of a simple loop calling the procedure New_Divide_Loop.
- The procedure itself, defined in lines 24 through 43, contains an
- example of a new operation, the ability to make up our own
- exception, raise it ourself, and handle it with our own exception
- handler.
-
-
- Page 17-3
-
- Chapter 17 - Exceptions
-
- Line 25 declares the identifier My_Own_Exception as being the name
- of an exception, and is defined in much the same way that we would
- declare a variable. We cannot assign a value to it, but we can
- raise it anywhere within its defined scope which is the same as the
- scope of a variable declared at the same place. The exception is
- automatically initialized to the "not raised" condition by the
- system.
-
- Beginning in line 37, we define three different exception handlers,
- which will cover any exceptions raised anywhere within this
- procedure. The first two are named exception handlers but the
- third handler uses the reserved word others to indicate that it
- will be used for any exceptions that are not handled by the two
- named exception handlers. The others clause is optional, but if
- it is included, it must be last.
-
-
-
- RAISING AN EXCEPTION
- _________________________________________________________________
-
- If we reach line 31 with a value of 4, which we eventually will
- because of the logic of the calling program, we will detect the
- divide by zero that would be attempted upon reaching line 34.
- Instead of letting the system generate the exception named
- Numeric_Error, we generate our own exception named
- My_Own_Exception, using the reserved word raise followed by the
- name of the exception. As soon as we raise this exception, the
- system jumps to the end of the block, looks for the reserved word
- exception, which it finds, then looks for the exception handler
- with the name that was raised. Upon finding it, the statements are
- executed, resulting in a message being output to the display, and
- a return is effected to the calling program.
-
- In this case, the system will not raise the exception
- Numeric_Error, because we are detecting the error before it
- actually happens. You could raise it yourself by inserting the
- statement "raise Numeric_Error;" somewhere in this procedure,
- possibly when the value of Index is equal to 3. It would be a good
- exercise for you to insert that in the code to see that you can
- raise one of the system exceptions as well as your own.
-
- Be sure to compile and execute this program to verify proper
- operation according to this description and to ascertain your
- understanding of the same.
-
- Note that if an exception occurs, formal parameters of mode out or
- in out are not updated since a normal return is not accomplished.
- Partial results will therefore not be returned to the calling
- program. This is not illustrated here, but is left for the student
- to investigate if desired.
-
-
-
-
- Page 17-4
-
- Chapter 17 - Exceptions
-
- WHAT ARE THE PREDEFINED EXCEPTIONS?
- _________________________________________________________________
-
- There are five predefined exceptions which can be raised by the
- system to indicate a very specific problem. A brief definition
- follows;
-
- Constraint_Error - This will occur if something goes out of its
- assigned range.
-
- Numeric_Error - This will occur if something goes wrong with
- arithmetic such as the attempt to divide by zero illustrated
- in this chapter.
-
- Program_Error - This will occur if we attempt to violate an Ada
- control structure such as dropping through the bottom of a
- function without a return.
-
- Storage_Error - This will occur if we run out of storage space
- through either recursive calls or storage allocation calls.
-
- Tasking_Error - This will occur when attempting to use some form
- of tasking in violation of the rules.
-
- All five of these exceptions are defined in detail in section 11.1
- of the LRM.
-
-
-
- WHAT ABOUT AN UNHANDLED EXCEPTION?
- _________________________________________________________________
-
- Examination of the program named EXCEPT3.ADA ===============
- will reveal what happens if an exception is EXCEPT3.ADA
- raised that is not handled by the program. In ===============
- a word, the program will be terminated, but we
- need to understand how termination occurs so we
- can intelligently prevent it.
-
- There is a loop in the main program which calls two procedures
- successively, Divide_By_Zero and Raise_An_Error. The first
- procedure is identical to that in the first two example programs
- and the only exception raised is Numeric_Error, which is handled
- properly.
-
- The second procedure has its own exception defined, named
- My_Own_Error which it raises and handles itself in the manner
- defined previously in this chapter. It also has a divide by zero
- problem in line 29 that will raise the exception Numeric_Error when
- Count is equal to 6. Of course, the logic is defined to make this
- happen and illustrate the error.
-
-
-
-
- Page 17-5
-
- Chapter 17 - Exceptions
-
- PROPAGATION OF EXCEPTIONS
- _________________________________________________________________
-
- When the exception Numeric_Error is raised at line 29, the system
- searches for the reserved word exception which it finds in line 34
- at the end of the procedure. It then searches for a sequence of
- statements for Numeric_Error which it does not find. Since an
- exception handler is not found within the procedure, the exception
- is propagated to the calling program in such a way that the
- exception appears to have been raised by the calling statement.
- In this case it will appear to the logic as if the exception
- Numeric_Error was raised by the statement in line 42. Once again,
- the exception rules are applied, and the system searches for an
- exception block at the end of the block or subprogram, in this case
- being the main program. Finding the reserved word exception in
- line 46, the system looks for the desired exception handler, which
- it finds and executes, then drops out of the bottom of the main
- program which initiates a return to the operating system.
-
- If there were no handler for the exception, the exception would be
- propagated to the operating system, and it would issue some sort
- of nasty message about an unhandled exception leading to program
- termination.
-
- It should be somewhat obvious to you that if you added another
- level of subprogram nesting, you could report the error yourself,
- and possibly recover operation of the program. It is all a matter
- of program definition.
-
-
- CAN YOU EXECUTE AN EXCEPTION WITHOUT RAISING IT?
- _________________________________________________________________
-
- As mentioned before, the section of code at the end of the program,
- following the reserved word exception, is never executed without
- raising an exception. It can never be executed by dropping into
- it.
-
- Be sure to compile and execute this program to observe the
- operation of the exceptions.
-
-
- EXCEPTIONS CAN OCCUR DURING DECLARATIONS
- _________________________________________________________________
-
- Examine the program named EXCEPT4.ADA for an ===============
- example of an exception that occurs during the EXCEPT4.ADA
- declaration part of the program. ===============
-
- When a procedure is called, its declarations are
- elaborated prior to the logic being executed, as we have stated
- before. If one of the declarations cannot be properly elaborated,
- then an error occurs and an exception is raised. Examining the
- procedure Try_It will reveal an error in lines 8 through 10, where
-
- Page 17-6
-
- Chapter 17 - Exceptions
-
- the variable Funny is declared to be of type LIMIT_RANGE with
- limits of 14 through 23, then it is initialized to the value 8.
- Since this is out of the allowed range, the exception
- Constraint_Error will be raised. The executable part of the
- procedure is not yet ready for use, so the exception handler
- defined within it cannot be used, and the exception will be
- propagated to the calling program where it will be handled just as
- if it occurred in the calling statement, which is line 22 in this
- case. The exception will therefore be handled by lines 24 through
- 26 of the procedure Try_To_Fix_It. Be sure to compile and run this
- program, then study the results.
-
-
- ADDITIONAL PREDEFINED EXCEPTIONS
- _________________________________________________________________
-
- You will find that there are actually additional exceptions
- predefined by your compiler, but these are all defined in
- additional packages supplied with your compiler. Packages such as
- Text_IO, Sequential_IO, or Calendar (to be discussed later with
- tasking), have some number of exceptions defined as a part of their
- interfaces, but there are only five exceptions predefined as a part
- of Ada. These were listed and discussed earlier.
-
-
- A FEW MORE TOPICS CONCERNING EXCEPTIONS
- _________________________________________________________________
-
- The example program named EXCEPT5.ADA ===============
- illustrates a few additional topics about EXCEPT5.ADA
- exceptions and illustrates how they are used in ===============
- a package. This is a very strange program with
- lots of exception handling examples for your
- study. You will be left on your own to study the overall operation
- of this program, but the unique exception handling techniques will
- be pointed out to you.
-
- The package body contains a section of initialization code in lines
- 37 through 48 which is composed of nothing but a null statement and
- several exception handlers. These are only used during
- initialization of the package since they are not within the
- executable portion of either of the subprograms. You will notice
- that the exception named Funny_Add_Error is declared in the package
- specification so it is visible in the exception handler in line 44,
- but the exception named Funny_Subtract_Error is not visible there
- because it is declared within the function. We will see soon
- however, that even this exception can be propagated to the main
- program.
-
- When the program is executing, a call to the function Subtract_One
- raises the exception Funny_Subtract_Error which is handled by the
- exception handler at the end of the function in line 32. A message
- is displayed and the same exception is raised by the isolated raise
- statement in line 34. This statement simply raises the exception
-
- Page 17-7
-
- Chapter 17 - Exceptions
-
- that caused the jump to the exception handler in the first place.
- The isolated raise statement can only be used within an exception
- handler. The exception is passed on to the calling program.
-
- Because the exception named Funny_Subtract_Error is not visible to
- the main program, it cannot handle it by name but even this
- exception can be handled by an others clause as is done in line 66.
- After printing a message, the same exception is once again raised
- in line 68 where it is passed on to the operating system. You will
- see when you execute this program that the exception is known by
- name to the operating system. It will give you a nasty message
- about an unhandled exception and terminate operation.
-
-
- THE others CLAUSE IN AN EXCEPTION HANDLER
- _________________________________________________________________
-
- If the others clause is used, it must be the last exception handler
- and it cannot be combined with any other exceptions such as
- illustrated in line 62. As in other Ada constructs, two or more
- exceptions can be "or"ed and use the same exception handler.
-
- Note line 57 where an exception is renamed to reduce the length of
- its name. Any exception can be renamed in a similar fashion.
-
- Be sure to compile and execute this program and spend the time
- necessary to understand the exception propagation illustrated here.
-
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Change line 34 of EXCEPT2.ADA to cause a divide by zero when
- Index is equal to 2 and see that both exceptions will be
- handled correctly.
-
- 2. Also in EXCEPT2.ADA, declare a new exception in line 25, and
- raise it in line 32 to see how the others clause handles it.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 17-8