You are on page 1of 10

AMITY INSTITUTE OF SPACE SCIENCE AND TECHNOLOGY,AMITY UNIVERSITY

Exception Handling
Avionics Software engineering
Prof M S Prasad
10/23/2014

This LN to be read in continuation with LN 3 , 3A . Prepared from open literature for students of
Grad/Post grad in Avionics .

SPAC 712 : ASE

Page 0

EXCEPTION HANDLING
Avionics Software Engineering : LN 3B
An exception is a situation that would be unusual for the program that is being processed. As a
programmer, we have to anticipate any abnormal behavior that could be caused by the user entering
wrong information that could otherwise lead to unpredictable results.
An error result or an unpredictable behavior on your program not caused by the operating system but
that occurs in your program is called an exception. The ability to deal with a programs eventual
abnormal behavior is called exception handling. C++ provides three keywords to handle an exception.
1. Trying the normal flow: To deal with the expected behavior of a program, use the trykeyword
as in the following syntax :
try { behavior}
The try keyword is required. It lets the compiler know that we are anticipating an abnormal
behavior and will try to deal with it. The actual behavior that needs to be evaluated is included
between an opening curly bracket { and a closing curly bracket }. Inside of the brackets,
implement the normal flow that the program should follow, at least for this section of the code.
2. Catching Errors: During the flow of the program as part of the try section, if an abnormal
behavior occurs, instead of letting the program crash or instead of letting the compiler send the
error to the operating system, we transfer the flow of the program to another section that can
deal
with
it.
The
syntax
used
by
this
section
is:
catch(Argument) {WhatToDo}

1.
2.
3.
4.
5.
6.
7.

This section always follows the try section and there must not be any code between the trys
closing bracket and the catch section. The catch keyword is required and follows the try section.
The catch behaves a little like a function. It uses an argument that is passed by the previous try
section. The argument can be a regular variable or a class. If there is no argument to pass,
the catch must at least take a three-period argument as in catch(). The behavior of
the catch clause starts with an opening curly bracket { and ends with a closing curly bracket
}. The inside of the brackets is called the body of the catch clause. Therefore, use the body of
the catch to deal with the error that was caused.
try {
// Try the program flow
}
catch(Argument)
{
// Catch the exception
}

3. Throwing an error: There are two main ways an abnormal program behavior is transferred from
the try block to the catch clause. This transfer is actually carried by the throw keyword. Unlike
the try and catch blocks, the throw keyword is independent of a formal syntax but still follows
some rules.
C++ Standard Exceptions:
C++ provides a list of standard exceptions defined in <exception> which we can use in our programs.
These are arranged in a parent-child class hierarchy shown below:

Exception

Description

std::exception

An exception and parent class of all the standard C++ exceptions.

std::bad_alloc

This can be thrown by new.

std::bad_cast

This can be thrown by dynamic_cast.

std::bad_exception

This is useful device to handle unexpected exceptions in a C++


program

std::bad_typeid

This can be thrown by typeid.

std::logic_error

An exception that theoretically can be detected by reading the code.

std::domain_error

This is an exception thrown when a mathematically invalid domain


is used

std::invalid_argument This is thrown due to invalid arguments.

std::length_error

This is thrown when a too big std::string is created

std::out_of_range

This can be thrown by the at method from for example a std::vector


and std::bitset<>::operator[]().

std::runtime_error

An exception that theoretically can not be detected by reading the


code.

std::overflow_error

This is thrown if a mathematical overflow occurs.

std::range_error

This is occured when you try to store a value which is out of range.

std::underflow_error

This is thrown if a mathematical underfl

An example
Class Dividebyzero
{ public :
Double divisor;
Dividebyzero(double x)
};
Dividebyzero::dividebyzero(double X) : divisor (X)
{ }
Int divide ( int X , int Y )
{ if ( Y == 0 )
{ throw Dividebyzero(X);
}
}
try
{ divide (12, 0);
}
Catch( dividebyzero divzero)
{cerr << attempt to divide <<divzero.divisor << by zero ;

}
In C++, a throw statement is used to signal that an exception or error case has occurred (think of
throwing a penalty flag). Signaling that an exception has occurred is also commonly called raising an
exception.
To use a throw statement, simply use the throw keyword, followed by a value of any data type you wish
to use to signal that an error has occurred. Typically, this value will be an error code, a description of the
problem, or a custom exception class.
In C++, we use the try keyword to define a block of statements (called a try block). The try block acts as
an observer, looking for any exceptions that are thrown by statements within the try block. Note that
the try block doesnt define HOW were going to handle the exception. It merely tells the program, if
you see an exception in the following code, grab it!.
Actually handling exceptions is the job of the catch block(s). The catch keyword is used to define a block
of code (called a catch block) that handles exceptions for a single data type.
Heres an example of a catch block:
catch (int)
{
// Handle an exception of type int here
cerr << "We caught an exception of type int" << endl;
}
Catching Multiple Exceptions
The exceptions as we have seen so far dealt with a single exception in a program. Most of the time, a typical
program will throw different types of errors. The C++ language allows you to include different catch blocks.
Each catch block can face a specific error. The syntax used is:
try {
Code to Try
}
catch(Arg1)
{
One Exception
}
catch(Arg2)
{
Another Exception
}

The compiler would proceed in a top-down as follows:


1. Following the normal flow control of the program, the compiler enters the try block.
2. If no exception occurs in the try block, the rest of the try block is executed.
If an exception occurs in the try block, the try displays a throw that specifies the type of error that
happened.
a. The compiler gets out of the try block and examines the first catch
b. If the first catch doesnt match the thrown error, the compiler proceeds with the next catch.
This continues until the compiler finds a catch that matches the thrown error.
c. If one of the catches matches the thrown error, its body executes. If no catch matches the thrown error, (or
the compiler has two alternatives. If there is no catch that matches the error (which means that you didnt
provide a matching catch), the compiler hands the program flow to the operating system (which calls
the terminate() function.
Another alternative is to include a catch whose argument is three periods: catch(). The catch() is used if
no other catch, provided there was another, matches the thrown error. The catch(), if included as part of
a catch clause, must always be the last catch, unless it is the only catch of the clause.
Multiple catches are written if or when a try block is expected to throw different types of error .
Nesting Exceptions
The compiler must first make sure that the user has entered a valid operator. Provided the operator is one
of those we are expecting, we also asked the compiler to check that valid numbers were entered. Even if
these two criteria are met, it was possible that the user enter 0 for the denominator.
The block that is used to check for a non-zero denominator depends on the exception that validates the
operators. In other words, before we check the value of the denominator, we have first made sure that a
valid number (a string that contains only digits and a period) was entered for the denominator. For this
reason, the exception that could result from a zero denominator depends on the user first entering a valid
number for the denominator.
C++ allows you to nest exceptions, using the same techniques we applied to nest conditional statements.
This means that you can write an exception that depends on, and is subject to, another exception. To nest
an exception, write a try block in the body of the parent exception. The nested try block must be followed
by its own catch(es). To effectively handle the exception, make sure you include an appropriate throw in
the try block.

Exceptions within functions


In all of the examples , the throw statements were placed directly within a try block. If this were a
necessity, exception handling would be of limited use.
One of the most useful properties of exception handling is that the throw statements do NOT have to be
placed directly inside a try block due to the way exceptions propagate when thrown. This allows us to

use exception handling in a much more modular fashion. Well demonstrate this by rewriting the square
root program from the previous lesson to use a modular function.
1

#include "math.h" // for sqrt() function

using namespace std;

// A modular square root function

double MySqrt(double dX)

// If the user entered a negative number, this is an error condition

if (dX < 0.0)

throw "Can not take sqrt of negative number"; // throw exception of type char*

return sqrt(dX);

10

11

int main()

12

13

cout << "Enter a number: ";

14

double dX;

15

cin >> dX;

16

try // Look for exceptions that occur within try block and sendto catch block(s)

17

18

cout << "The sqrt of " << dX << " is " << MySqrt(dX) << endl;

19

20

catch (char* strException) // catch exceptions of type char*

21

22

cerr << "Error: " << strException << endl;

23

}
}

The most interesting part of this program is the MySqrt() function, which potentially raises an exception.
However, note that this exception is not inside of a try block! This essentially means MySqrt is willing to
say, Hey, theres a problem!, but is unwilling to handle the problem itself. It is, in essence, delegating
that responsibility to its caller (the equivalent of how using a return code passes the responsibility of
handling an error back to a functions caller).

Lets see what happens when an exception is raised. First, the program looks to see if the exception can
be handled immediately (which means it was thrown inside a try block). If not, it immediately
terminates the current function and checks to see if the caller will handle the exception. If not, it
terminates the caller and checks the callers caller. Each function is terminated in sequence until a
handler for the exception is found, or until main() terminates. This process is called unwinding the
stack .
Now, lets take a detailed look at how that applies to this program when MySqrt(-4) is called and an
exception is raised.
First, the program checks to see if were immediately inside a try block within the function. In this case,
we are not. Then, the stack begins to unwind. First, MySqrt() terminates, and control returns to main().
The program now checks to see if were inside a try block. We are, and theres a char* handler, so the
exception is handled by the try block within main(). To summarize, MySqrt() raised the exception, but
the try/catch block in main() was the one who captured and handled the exception.
As a summary, when an exception is thrown, it may be caught by the following types of catch handlers:
1. A handler that can accept any type (using the ellipsis syntax).
2. A handler that accepts the same type as the exception object; because it is a copy, const
and volatile modifiers are ignored.
3. A handler that accepts a reference to the same type as the exception object.
4. A handler that accepts a reference to a const or volatile form of the same type as the
exception object.
5. A handler that accepts a base class of the same type as the exception object; since it is a
copy, const and volatile modifiers are ignored. The catch handler for a base class must
not precede the catch handler for the derived class.
6. A handler that accepts a reference to a base class of the same type as the exception
object.
7. A handler that accepts a reference to a const or volatile form of a base class of the same
type as the exception object.
8. A handler that accepts a pointer to which a thrown pointer object can be converted via
standard pointer conversion rules.
C++ exception is automatically calls destructor functions during the stack unwinding process, for all
local objects constructed before the exception was thrown.
Uncaught/Unhandled Exception
When the system can't find a handler for an exception, it calls the standard library
function terminate(), which by default aborts the program. We can substitute our own
termination function by passing a pointer to it as a parameter to the set_terminate() library
function.
An exception caught by a pointer can also be caught by a void* handler.
C++ (as described in the C++ Standards), allows you to specify that a function is an exception carrier. If
you write a function that carries an exception, you can type the throw keyword followed by parentheses
on the right side of the function.
----------------------------------------------------------------------------------------------------------------------

Error handling In C
C programming does not provide direct support for error handling (also called exception handling),
there are ways to do error handling.
Of course the programmer needs to prevent errors during coding and should always test the return
values of functions called by the program. A lot of C function calls return a -1 or NULL in case of an
error, so quick test on these return values can easily be done with for instance an if statement.
So the one thing we need to remember is that the programmers are responsible for error handling.
Global Variable errno
The global variable errno is used by C functions and this integer is set if there is an error during the
function call. To make use of errno , we need to include errno.h and need to call extern int errno;
Iit is also a good practice to give a good descriptive error message when an error occurs in the
program. The C programming language has two functions that can be used to display a text message
that is associated with errno. The functions are strerror() and perror().
The function strerror() returns a pointer to the textual message of the current errno value. The
function perror() displays a string you pass to it, followed by a colon and the textual message of the
current errno value. It is important to note that you should always use stderr file stream to output
all of the errors that may occur. Example
# include <stdio.h>
#include< error . h> / * to get the error no for the error * /
#include< string .h> /* this to print the string or message , needs to be included else we get
segmentation fault* /
extern int errorno;
int main ()
{ FILE =* fp;
fp= fopen( file1.txt, rb );
if fp = NULL
{ fprinf (stderr, value of errorno is :%d \n , errorno) ;
fprinf (stderr, error opening file : %s \n ,stderr( errorno)) ;
perror (, error printed ) ;
} else { fclose(fp) ;}
} return 0;

}
The output of this is
Value of error no : 3
Error opening file : No such file or directory exists
Error printed : No such file or directory exists .
First we print the errno. Then we use strerror() function to give a message of our own and print the
text representation of errno. Then perror() function is used to give a message of our own, followed
by a colon and the textual representation of errno.
----------------------------------------------------------------------------------------------------------------------

You might also like