Activity 17-4 - Programming Techniques for Exception Handling



So we talked about exception handling and went through some examples, but we never discussed how to make a good and realistic use of exception handling.

When to Throw an Exception
In complicated programs you may want to separate throwing an exception and catching the exception into separate functions.  In most cases, you should include any throw-statement within a function definition, list the exception in the exception specification for that function, and place the catch-clause in a different function.  Here is a preferred way to do this:

void functionA( ) throw (MyException)
{
        ...
        ...
        ...
        throw MyException(<Maybe an argument>);
        ...
        ...
        ...
}

Then in some other function we will have:

void functionB( )
{
        ...
        ...
        ...
    try
    {
        ...
        ...
        ...
        functionA( );
        ...
        ...
        ...
    }
    catch(MyException e)
    {
        <Handle exception>
    }
        ...
        ...
        ...
}
 

In general, you want to use throw-statements within functions listed in a exception specification for the function.

Testing for Available Memory
Sometimes we create dynamic variables with code such as:

struct Node
{
    int data;
    Node *link;
};

typedef Node* NodePtr;
        ...
        ...
NodePtr pointer = new Node;

This works fine without any problem but will cause a segmentation fault when there is not enough memory.  Since new throws a bad_alloc exception when there is not enough memory to create the node, we can use it to check whether we will run out of memory:

try
{
        NodePtr  pointer = new Node;
}
catch(bad_alloc)
{
        cout << "Run out of memory!";
}

You can do other things besides giving a warning message, for example, you can set the value to zero or to a very large number.

Exercise 17.4
Use the suggestions that are given for exception handling in this activity and re-write ex17.3.