Professional Documents
Culture Documents
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 .
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
std::bad_alloc
std::bad_cast
std::bad_exception
std::bad_typeid
std::logic_error
std::domain_error
std::length_error
std::out_of_range
std::runtime_error
std::overflow_error
std::range_error
This is occured when you try to store a value which is out of range.
std::underflow_error
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
}
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
throw "Can not take sqrt of negative number"; // throw exception of type char*
return sqrt(dX);
10
11
int main()
12
13
14
double dX;
15
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
21
22
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.
----------------------------------------------------------------------------------------------------------------------