Exception Handling

Submitted by coleen.yan@edd… on Mon, 04/22/2024 - 17:55
Sub Topics

It might be easier to write a program assuming there is nothing that will go wrong, but sometimes it’s easy to overlook coding errors or it may be that the errors that may happen are out of your control.

A common example of this is when you use your mobile phone. You dial in a number that is not already in your contacts list but instead of it ringing a message comes through that the number you have dialled is incorrect or no longer assigned. The workings behind the interface you see and interact with, have flagged the problem and sent you a pre-recorded message. If you misdialed the number, you would get a message asking you to try again. This is Exception Handling.

What is an exception?

An exception is a problem that arises during the running of a program. It’s a response to, an exceptional circumstance that arises while a program is running. It could be the result of a calculation trying to divide by zero or a user inputting incorrect information. Exceptions provide a way to react to exceptional circumstances in programs (such as runtime errors) by handing over control to special functions referred to as handlers that throw the exception from inside a try block. Handlers are declared with the keyword catch, which are placed directly after the try block. This topic is all about how this works in different circumstances

Exception Handling

Exception handling is a new feature of C++, and most C++ compilers support this new feature. Exception handling in C++ provides a way of handling unexpected circumstances in your program such as runtime errors. Whenever an error happens, the control of the program is transferred to special functions known as handlers.

There are two types of exceptions:

  1. Synchronous
  2. Asynchronous

Errors that occur internally or that are out of range, or deal with overflow etc., are synchronous type exceptions. Those errors cause outside of internal events and are beyond the control of the program are asynchronous exceptions. The main role of exception handling is to provide a way of detecting and reporting problems so the appropriate action can be taken. It needs to:

  • find the problem (exception)
  • identify and inform the problem has occurred (throw the exception)
  • receive the error information (catch the exception)
  • take action to correct the problem (handle exception)

The error code basically consists of two segments, one to detect errors and to throw exceptions and the other to catch the exceptions and take appropriate actions.

 

To catch exceptions, code is written under a catch block. There are based on three keywords:

  • try – identifies the code block for which certain exceptions will be monitored and activated. This should be followed by one or more catch blocks. Functions called from within a try block may also throw an exception.
  • throw – when a program encounters a problem (i.e. an error), it throws an exception. The throw keyword helps the program perform the throw.
  • catch – a program catches an exception using exception handlers. It’s added to the section of program where you need to handle the problem. It’s done using the catch keyword.

Syntax:

 

Exceptions mechanisms

A diagram depicting Exceptions mechanisms

Although there is only one try statement, there can be more than one catch block. The exception name is the name of the exception to be caught and the exception 1, exception etc are your defined names for referring to the exceptions.

 
  • If an exceptional situation occurs within the try section of code, an exception is thrown so the handler takes over the program.
  • If the try block throws an exception, then program control shift from the block and enters into the catch statement of the catch block.
  • If the type of object thrown matches the argument in the catch statement, the catch block is executed to handle the exception.
  • You can design a program to throw as many exceptions as you want.
 

It works like this:

A throw expression accepts one parameter which is passed to the exception handler. The exception handler is declared with the catch keyword immediately after the closing bracket of the try block. The syntax for catch is like a regular function with one parameter. The type of this parameter is very important, as the type of the argument passed by the throw expression is checked against it and only if they match, the exception will be caught by that handler.

Catch All:

Multiple catch expressions (handlers) can be chained, each with their own parameter type. Only the handler whose argument matches the exception type specified in the throw statement is executed.

Example:

 

In this situation the last catch block (handler – catch all) would catch any exception thrown of a type that isn’t already declared.

Note: Once a handle has been handled, the program execution begins after the try-catch block, not the throw statement.

You can also use try-catch blocks within more external try blocks. This is done using the expression throw; with no arguments:

 

In this situation it is possible that an internal catch block will forward the exception to its external level.

The try block can be a short as a few statements within one function or as an all broad as enclosing the main() function code within a try block which effectively causes the entire program to be monitored for errors.

You can also throw an exception from a function outside the try block.

 

Output:

Start
Inside try block
Inside Xtest, test is: 0
Inside Xtest, test is: 1
Caught an exception -- value is: 1
End

A try block can be localised to a function. When this is done, each time the function is entered the exception handling relative to that function is reset. Open the code example below and run the program.

  • What is the output?
  • Change Xhandler(1) value to a 0. What is the output now?

You will have seen that three exceptions were thrown and after each exception the function returned. When the function is called again the exception handling is reset. The code associated with a catch statement will be executed ONLY if it catches an exception, otherwise execution simply bypasses the catch altogether. Where an exception is not thrown, the catch statement does not execute. It’s also described as ‘no match, no catch’.

Watch Codearchery as they explain exception handling using a bank deposit as an example so you understand basic coding around this new topic. It’s a great place to start.

Thenewnboston explains the basics of exceptions using code examples. You can also continue onto tutorial #63 More Exception Examples

Now it’s your turn. Write a small program based to demonstrate exception handling for two integers division for a Divde by zero error.

Practice 1

Write a simple C++ program to demonstrate exception handling for two integers division for a divide by zero error.

Here’s an example:

 

Why exception handling?

There are three main advantages of exception handling over tradition error handing:

  1. Separating error handling from normal code
  2. Functions/methods can handle any exceptions they choose
  3. Group error types

In traditional handling of errors there are always if else conditions to handle errors. These along with the code can get mixed up with the normal flow of the code. It makes the code difficult to read which means hard to maintain. When we use try blocks, the code for the error becomes separate from the normal flow.

A function can throw many exceptions but may choose to handle some of them. The others that are thrown but not caught can be handled by the caller. Or the caller of the caller. In C++ a function can specify the exceptions it throws by using the throw keyword. The caller of this function MUST handle the exception in some way. This might be through specifying it again or catching it.

Both types and objects can be thrown as an exception in C++. We can create a hierarchy of exceptions objects, group exceptions in namespace or classes, and categorise them according to types.

Look at this simple exception handling example.

Run the code to find the output.

An explanation of the practice program:

There is a try block containing three statements and a catch(int i) statement that processes an integer exception.

Within the try block, only two of the three statements will execute: the first cout statement and the throw. Once an exception has been thrown, control passes to the catch expression and the try block is terminated.

The catch is not called. Rather, program execution is transferred to it. This means the cout statement following the throw will never execute.

Usually, the code within a catch statement attempts to remedy an error by taking appropriate action. If the error can be fixed, execution will continue with the statements following the catch. However, often an error cannot be fixed and a catch block will terminate the program with a call to exit() or abort().

Make a change to the program

What happens if you change the type in the catch statement to double? Run the program to find out.

When the catch does not match the throw:

If you change the type in the catch statement to double as you were asked to do in the exercise above, the exception will not be caught, and an abnormal termination will occur. The integer exception will not be caught by the catch double statement and the output would show something similar to this:

Output:

Start
Inside try block
Abnormal termination

Also see this example:

 

Output:

Start
Inside try block
Still inside try block
End

Catching class types

An exception can be of any type that you create, but in real world programs, most exceptions will be class types rather than built in types. The most common reason you will want to define a class type for an exception is to create an object that describes the error. This information can be used by the exception handler to help it process the error.

 

Output:

Enter a positive number: 4
Not positive: -4

Using multiple catch statements

We already know that is common to have more than one catch associated with a try, but each catch must catch a different type of exception. The following program catches both integers and stings.

You will use the program you changed previously for this practice.

Change the code in the program to match what’s below:

 

Did you get this output? As you can see each catch statement only responded to its own type. Only matched statements are executed, all others are ignored.

Start
Caught Exception #: 1
Caught Exception #: 2
Caught a string: Value is zero
Caught Exception #: 3
End

Standard exceptions in C++

The C++ standard library provides a base class specifically designed to declare objects to be thrown as exceptions. It’s called std::exceptions. This is defined in the <exception> header.

The C++ std::exceptions class allows us to define objects that can be thrown as exceptions. The class provides us with a virtual member function named what. This function returns a null-terminated character sequence of type char*. We can overwrite it in derived classes to have an exception description.

We have placed a handler that catches exception objects by reference (notice the ampersand & after the type), therefore this catches also classes derived from exception, like our myex object of type my exception.

 

Output:

My exception happened.

My exception happened output diagram

Exception Description
std::exception An exception and parent class of all standard C++ exceptions
std::bad_alloc An exception thrown by a new keyword
std::bad_cast An exception thrown by dynamic_cast
std::bad_exception Useful device for handling unexpected exceptions in C++ programs
std::bad_typeid An exception thrown by typeid
std::logic_error This exception is theoretically detectable by reading code
std::domain_error Exception thrown after using a mathematically invalid domain
std::invalid_argument An exception thrown for using invalid arguments
std::length_error An exception thrown after creating a big std::string
std::pit_of_range Thrown by at method
std::runtime_error An exception that cannot be detected via reading the code
std::overflow_error Exception thrown after the occurrence of a mathematical overflow
std::range_error Exception thrown when you attempt to store an out-of-range value
std::underflow_error Exception thrown after the occurrence of mathematical underflow

For more information cpp exceptions handling, read more about it at guru99.com.

Exception specification: Pre C++

Older code may contain dynamic exception specifications. These are no longer used in C++, but are still supported. For example:

 

This declares a function names myfunction which takes one argument of type and returns a value of type double. Should this throw an exception of some type other than int, the function call std::unexpected (from the std::exception parent class) rather than looking for the exception handler or calling on std::terminate.

If the throw specifier is left empty, without type this means that std::unexpected is call for any exception. Functions with no throw specifier never call std::unexpected, they follow the normal path for finding their exception handler. For example:

 

If statements:

If statements can be used to control exception handling:

 

While using if statements is one way of handling exceptions, in complex programming, it would not be practical to have if statements everywhere.

A programmer using a laptop Computer in a stylish office workspace

Catching all exceptions:

You may want an exception handler to catch all exceptions instead of just a certain type

 

Output:

Start
Caught One!
Caught One!
Caught One!
End

Restricting Exceptions:

You can restrict the type of exceptions that a function can throw outside of itself. In fact, you can also prevent a function from throwing any exceptions whatsoever. To accomplish these restrictions, you must add a throw clause to a function definition

 

Here, only those data types contained in the comma-separated type-list may be thrown by the function. Throwing any other type of expression will cause abnormal program termination. If you don't want a function to be able to throw any exceptions, then use an empty list. Attempting to throw an exception that is not supported by a function will cause the standard library function unexpected() to be called. By default, this causes abort() to be called, which causes abnormal program termination.

All three throws were caught using the one catch statement. One very good use for catch(...) is as the last catch of a cluster of catches. In this capacity it provides a useful default or "catch all" statement. For example, this slightly different version of the preceding program explicitly catches integer exceptions but relies upon catch(...) to catch all others. As this example suggests, using catch(...) as a default is a good way to catch all exceptions that you don't want to handle explicitly. Also, by catching all exceptions, you prevent an unhandled exception from causing an abnormal program termination.

 

Output:

Start
Caught an integer
Caught One!
Caught One!
End

In this program, the function Xhandler() may only throw integer, character, and double exceptions. If it attempts to throw any other type of exception, an abnormal program termination will occur. (That is, unexpected() will be called.) To see an example of this, remove int from the list and retry the program.

It is important to understand that a function can be restricted only in what types of exceptions it throws back to the try block that called it. That is, a try block within a function may throw any type of exception so long as it is caught within that function.

The restriction applies only when throwing an exception outside of the function. The following change to Xhandler() prevents it from throwing any exceptions.

Practice 2

Write a c++ program with the following

  1. A member function to get two double type numbers from user
  2. A member function to calculate the division of these two numbers
  3. A try block to throw an exception class type when a wrong type of data is entered
  4. A try block to detect and throw an exception if the condition divide by zero occurs
Module Linking
Main Topic Image
A person in smart casual wear working on laptop while sitting near window.
Is Study Guide?
Off
Is Assessment Consultation?
Off