C++ Exception Handling

Detecting abnormal behavior of the software at the runtime and taking preventive measure is called exception handling.

  • Exceptions are errors that occur at runtime. They are caused by a wide variety of exceptional circumstance, such as running out of memory, not being able to open a file, trying to initialize an object to an impossible value, or using an out-of-bounds index to a vector.
  • The function that cannot handle problem throws the exception to its caller to handle it. A function that wants to handle that kind of problem can indicate that it is willing to catch the exception.
  • Exception handling can be used to support ideas of error handling and fault tolerant computing.
  • Fault tolerance approach attempts to increase reliability by designing the system to continue to provide service in spite of the presence of faults.

 

Basics of exception handling

Syntax:

int main() { 
   try { 
      //. . . 
   } catch(. . .) { 
      //. . . 
   } 
}

Working

  • When a problem is detected during the computation, an exception is raised by using keyword throw.
  • The raised exceptions are handled by the catch block. This exception handler is indicated by the keyword catch. The catch construct must be used immediately after the try block.
  • try block is responsible for testing the existence of exceptions.

The following figure explains more about this.

exception handling

 

Steps taken during exception handling

1. Hit the exception (detect the problem causing exception)
2. Throw the exception (inform that an error has occurred)
3. Catch the exception (receive the appropriate actions)
4. Handle the exception(take appropriate actions)

exception handling mechanism

The following code snippet shows how exception handling works.

function1()
{
    //. . .
    if(operation_fails) throw obj1;
}
function2()
{
    // . . .
    try
    {
        function1();
        //. . .
        if(operation_fails) throw obj2;
    }
    catch(type1 ob1)     //handle appropriate actions
    {
        //. . .
    }
    catch(type2 ob2)     //handle appropriate actions
    {
        //. . .
    }
}

When an exception is raised, following sequence of steps is performed:

1. First, the program searches for a matching handler.
2. If any matching handler is found, the stack is unwound to that point.
3. The program control is transferred to the handler.
4. If handler is not found, the program will call the function terminate ().

 

Example

Lets look at the program that finds the square root of input number if it is positive and throws exception if input number is negative.

//an example of exception handling
#include<iostream>
#include<cmath>
using namespace std;
class number
{
private:
    double num;
public:
    class NEG {}; //exception class
    void readnum()
    {
        cout<<"Enter number: ";
        cin>>num;
    }
    double sqroot()
    {
        if(num<0)
            throw NEG();
        else
            return (sqrt(num));
    }
};
int main()
{
    number n1;
    double result;
    n1.readnum();
    try
    {
        cout<<"\n Trying to find square root . . .";
        result=n1.sqroot(); //interacts with class; may cause error
        cout<<"\n Square root is: "<<result<<endl;
        cout<<"Success . . . Exception is not raised."<<endl;
    }
    catch(number::NEG)
    {
        cout<<"\n Square root of negative number not possible!"<<endl;
    }
    return 0;
}

Here, if sqroot() detects the error and raises an exception by passing a nameless object of type class NEG. And important point to note is that runtime system searches catch block to detect the handler.

So, the output of the program is:

Enter number: 4 
Trying to find square root . . .
Square root is: 2
Success . . . Exception is not raised.

And if you input negative number, then output is:

Enter number: -4
Trying to find square root . . .
Square root of negative number not possible!
C++ Virtual Function
C++ Templates