Error Handling
There are mainly two types of bugs, logical errors and syntactic errors. The logical errors occur
due to poor understanding of problem and syntactic errors arise due to poor understanding of
language. There are some other problems called exceptions that are run time anomalies or
unused conditions that a program may encounter while executing, which in turn cause the
program to fail.
Exceptions are classified into two types
Synchronous
The exceptions which occur during the program execution, due to some fault in the input-data or
technique that is not suitable to handle the current class of data, within the program, are known
as synchronous exceptions. For instance, errors such as out-of-range, overflow, underflow, and
so on belong to the class of synchronous exceptions.
Asynchronous
The exceptions caused by events or faults unrelated (external) to the program and beyond the
control of program are called asynchronous exceptions. Such as keyboard interrupts, hardware
malfunctions, disk failure etc.
Exception handling mechanism in C++ is designed to handle only synchronous exceptions. Most
C++ compilers are support-ing the exception-handling model. When an abnormal situation arises
at runtime, the program should terminate. However, throwing an exception allows the user to
gather information at the throw point that could be useful in diagnosing the causes which led to
failure. A user can also specify in the exception handler the actions to be taken before the
program terminates.
Exception Handling Model
When a program encounters an abnormal situation for which it is not designed, the user may
transfer control to some other part of the program that is designed to deal with the problem. This
is done by throwing an exception. The exception-handling mechanism uses three blocks: try,
throw and catch. The relationship of these three exception handling constructs called the
exception handling model
The purpose of exception handling mechanism is to detect and report exceptional circumstances so
that appropriate action can be taken. The mechanism for exception handling is
1. Find the problem (hit the exception).
2. Inform that an error has occurred (throw the exception).
3. Receive the error information (Catch the exception).
4. Take corrective actions (Handle the exception)
The error handling code mainly consists of two segments, one to detect error and throw
exceptions and other to catch the exceptions and to take appropriate actions.
The try-block must be followed immediately by a handler, which is a catch block. If an exception
is thrown in the try-block, the program control is transferred to the appropriate exception
handler. The program should attempt to catch any exception that is thrown by any function.
Failure to do so could result in abnormal termination of the program.
Exception handling mechanism
C++ exception handling mechanism is basically built upon three keywords namely try, throw
and catch. The keyword try is used to preface a block of statements which may generate
exceptions. This block of statement is called try block. When an exception is detected it is
thrown using throw statement in the try block. A catch block defined by the keyword catch
‘catches’ the exception thrown by the throw statement in the try block and handles it
appropriately. The catch block that catches an exception must immediately follow the try block
that throws the exception. The general form for this is ……………….
………………..
try
{
…………
……………..//block of statements which detects and throw an exception
throw exception;
…………….
…………….
}
catch (type arg) //catches exceptions
{
…………… // Block of statements that handles the exceptions
………………
…………….
}
………….
…………..
When the try block throws an exception, the program control leaves the try block and enters the
catch statement of the catch block. If the type of object thrown matches the arg type in the catch
statement, then the catch block is executed for handling the exception. If they do not match, the
program is aborted with the help of abort() function which is executed implicitly by the compiler.
When no exception is detected and thrown, the control goes to the statement immediately after
the catch block i.e catch block is skipped. The below diagram will show the mechanism of
exception handling.
Example:
#include<iostream>
using namespace std;
int main()
{
int a,b;
cout<<”enter the values of a and b”;
cin>>a;
cin>>b;
int x = a- b;
try
{
if(x!=0)
{
cout<<”result(a/x) = “<<a/x<<”\n”;
}
else
{
throw(x);
}
}
catch(int i)
{
cout<<”exception caught : x = “<<x<<”\n”;
}
cout<<”end”;
return 0;
}
The program detects and catches a division by zero exception. When no exception is thrown, the
catch statement is skipped and execution resumes with the first line after the catch. But, if the
denominator x become zero and therefore a division by zero situation occurs. This exception is
thrown using the object x. Since the exception object is of integer type, the catch statement
containing int type argument catches the exception and displays necessary message.
The exceptions are thrown by functions that are invoked from within the try block. The point at
which the throw is executed is called throw point. Once an exception is thrown to catch block,
control cannot return to the throw point.
Function throwing exception
The exceptions are also thrown by functions that are invoked from within the try block. The point at
which the throw is executed is called throw point. Once an exception is thrown to catch block,
control cannot return to the throw point.
The below program demonstrates how a try block invokes a function that generates an exception
type function (arg list) //function with exception
{
……………
throw(object); //throw exception
………..
………..
}
………
………….
try
{
………. Invoke function here
………..
}
catch(type arg) //catches exception
{
…………..
…………. Handle exception here
………….
}
………..
It is to be noted here that the try block is immediately followed by the catch block irrespective of the
location of the throw point.
# include <iostream>
using namespace std;
void divide (int x,int y,int z)
{
cout<<”we are outside the function”;
if ( ( x-y) != 0)
{
int r=z/(x-y);
cout<<”result = “<<r;
}
else
{
throw(x-y);
}
}
int main()
{
try
{
cout<<”we are inside the try block”;
divide(10,20,30);
divide(10,10,20);
}
catch (int i)
{
cout<<”caught the exception”;
}
return 0;
}
Throwing mechanism
When an exception is encountered it is thrown using the throw statement in the following form:
throw (exception);
throw exception;
throw;
The operand object exception may be of any type including constants. It is also possible to throw
objects not intended for error handling. When an exception is thrown, it will be caught by the
catch statement associated with the try block. In other words the control exits the try block and
transferred to catch block after the try block. Throw point can be in the deep nested scope within
the try block or in a deeply nested function call.
Catching mechanism
Code for handling exceptions is included in catch blocks. The catch block is like a function
definition and is of form
Catch(type arg)
{
statements for managing exceptions
}
The type indicates the type of exception that catch block handles. The parameter arg is an
optional parameter name. The catch statement catches an exception whose type matches with the
type of catch argument. When it is caught, the code in the catch block is executed. After
executing the handler, the control goes to the statement immediately following in catch block.
Due to mismatch, if an exception is not caught abnormal program termination will occur. In
other words catch block is simply skipped if the catch statement does not catch an exception.
Multiple Catch Statements
In some situations the program segment has more than one condition to throw an exception. In
such case more than one catch blocks can be associated with a try block as shown below
try
{
//try block
}
catch(type1 arg)
{
//catch block1
}
catch(type 2 arg)
{
//catch block 2
}
……………..
…………….
catch (type N arg)
{
//catch block N
}
When an exception is thrown, the exception handlers are searched in order for an appropriate
match. The first handler that yields a match is executed. After executing the handler, the control
goes to the first statement after the last catch block for that try. When no match is found, the
program is terminated. If in some case the arguments of several catch statements match the type
of an exception, then the first handler that matches the exception type is executed.
#include <iostream>
using namespace std;
void test (int x)
{
try
{
if (x==1)
throw x; //int
else
if(x==0)
throw ‘x’; //char
else
if (x== -1 )
throw 1.0; //double
cout<<”end of try- block \n”;
}
catch(char c) //Catch 1
{
cout<<”Caught a character \n”;
}
catch (int m) //Catch 2
{
cout <<”caught an integer\n”;
}
catch (double d) //catch 3
{
cout<<”caught a double \n”;
}
cout<<”end of try –catch system \n\n”;
}
int main()
{
cout<<”Testing multiple catches \n”;
cout<<”x== 1 \n”;
test(1);
cout<<”x== 0 \n”;
test(0);
cout<<”x == -1 \n”;
test (-1);
cout <<”x== 2 \n”;
test (2);
return 0;
}
The program when executed first invokes the function test() with x=1 and throws x an int
exception. This matches the type of parameter m in catch 2 and therefore catch2 handler is
executed. Immediately after the execution, the function throws ‘x’, a character type exception
and therefore the first handler is executed. Finally the handler catch3 is executed when a double
type exception is thrown. Every time only the handler which catches the exception is executed
and all other handlers are bypassed.
Catch All Exceptions
In some cases when all possible type of exceptions cannot be anticipated and may not be able to
design independent catch handlers to catch them, in such situations a single catch statement is
forced to catch all exceptions instead of certain type alone. This can be achieved by defining the
catch statement using ellipses as follows
CATCHING ALL EXCEPTIONS
#include <iostream>
using namespace std;
void test(int x)
{
try
{
if (x== 0)
throw x; //int
if ( x== -1)
throw ‘x’; //char
if ( x== 1)
throw 1.0; //float
}
catch(. . .) //catch all
{
cout<<”caught an exception \n”;
}
}
int main()
{
cout<<”testing generic catch\n”;
test(-1);
test(0);
test(1);
return 0;
}
We can use the catch(. . .) as a default statement along with other catch handlers so that it can
catch all those exceptions that are not handled explicitly.
Rethrowing an Exception
A handler may decide to rethrow an exception caught without processing them. In such
situations we can simply invoke throw without any argument like throw; This cause the current
exception to be thrown to the next enclosing try/catch sequence and is caught by a catch
statement listed after that enclosing try block. The following program shows how an exception is
rethrown and caught.
RETHROWING AN EXCEPTION
#include <iostream>
using namespace std;
void divide(double x, double y)
{
cout<<”Inside Function \n”;
try
{
if (y== 0.0)
throw y; //throwing double
else
cout<<”division = “<< x/y<<”\n”;
}
catch(double) //Catch a double
{
cout<<”Caught double inside a function \n”;
throw; //rethrowing double
}
cout<<”end of function\n\n”;
}
int main()
{
cout <<”inside main \n”;
try
{
divide(10.5,2.0);
divide(20.0,0.0);
}
catch (double)
{
cout <<”caught double inside main \n”;
}
cout <<”End of main “;
return 0;
}
When an exception is rethrown, it will not be caught by the same catch statement or any other
catch in that group. It will be caught by the an appropriate catch in the outer try/catch sequence
for processing.
Specifying Exceptions
In some cases it may be possible to restrict a function to throw only certain specified exceptions.
This is achieved by adding a throw list clause to function definition. The general form of using
an exception specification is:
Type function (arg-list) throw (type-list)
{
…………..
………… function body
……….
}
The type list specifies the type of exceptions that may be thrown. Throwing any other type of
exception will cause abnormal program termination. To prevent a function from throwing any
exception, it can be done by making the type list empty like
throw(); //empty list
in the function header line.
#include <iostream>
using namespace std;
void test (int x) throw (int,double)
{
if (x== 0)
throw ‘x’; //char
else
if (x== 1)
throw x; //int
else
if (x== -1)
throw 1.0; //double
cout <<”End of function block \n “;
}
int main()
{
try
{
cout<<”testing throw restrictions\n”;
cout<<”x== 0\n “;
test (0);
cout<<”x==1 \n”;
test(1);
cout<<”x== -1 \n”;
test(-1);
cout <<”x== 2 \n”;
test(2);
}
catch( char c)
{
cout <<”caught a character \n”;
}
catch(int m)
{
cout<<”caught an integer \n”;
}
catch (double d)
{
out<<”caught a double \n”;
}
cout<<” end of try catch system \n \n”;
return 0;
}