An exception is an error that occurs at run time. Exceptions can be caused by external factors, such as insufficient resources, or internal factors such as an invalid pointer.C++’s exception-handling handles run-time errors in a structured and controlled manner. When an exception occurs a program can automatically invoke an error-handling routine to deal with the problem.
C++ exception handling is implemented using the three keywords: try, catch, and throw. Program statements can be monitored for exceptions in a try block. If an exception or error occurs within that try block, it is said to be 'thrown'. This thrown exception is caught by the appropriate catch statement, which then processes the exception. There can be more than one catch statement associated with any try. C++ provides a list of standard exceptions, in addition, the user can define their own exceptions by overriding exception class functionality. Exceptions can be generated anywhere within a code block using a throw statement.
In the sample code below the user is requested to enter a value to reserve memory space on the freestore. Entering a value lower than zero throws a standard bad allocation exception; attempts to enter an alphanumeric value, or zero will result in a user-defined exception.
#include <iostream> #include <exception> // include this to catch exception bad_alloc using namespace std; int main() { cout << "Enter number of integers you wish to reserve: "; try { int input = 0; cin >> input; if (!cin) //user initiated throw statements. Responds to non numeric values { throw 1; throw "Entered value is not a valid integer"; } else if (input==0) //user initiated throw statements. Responds to zero throw "Entered value is a zero"; int* numArray = new int [input];// Request memory space and then return it cout << numArray; delete[] numArray; } catch (std::bad_alloc& exp) { cout << "Exception encountered: " << exp.what() << endl; } catch (const char *message) { cout << message << endl; } catch (const int message) { cout << message << endl; } catch(...) { cout << "Program terminating" << endl; } return 0; }
C++ Standard Exceptions
C++ provides a list of standard exceptions defined in the header file. A small sample of these is listed below
Exception | Description | |
std::exception | base class for exceptions thrown by the standard library components | |
std::bad_alloc | Thrown after a failure to allocate the requested storage space by the operator new. | |
std::bad_cast | The exception is thrown by dynamic_cast when it fails the run-time check | |
std::bad_exception | Handles unexpected exceptions in a C++ program | |
std::logic_error | reports errors that are a consequence of faulty logic within the program | |
std::length_error | Thrown when a std::string is to large when created | |
std::out_of_range | Reports errors that are a consequence of an attempt to access elements out of defined range. | |
std::overflow_error | Thrown in the event of a mathematical overflow | |
std::underflow_error | Thrown in the event of a mathematical underflow< |
Creating a User-Defined exception class
A user-defined exception can be created by inheriting and overriding the base exception class found in the <exception> header. Using the std::exception class ensures that all existing exception handlers will automatically scale up to catch your new exception class as well because they share the same base class.
In the code sample below the user is asked to enter a positive integer value. The input is checked in the try block first for any values equal to and then lower than zero. Any unacceptable data will trigger an exception. what() is a public method provided by the exception class. It is used to return the cause of an exception.
#include <iostream> #include <exception> using namespace std; class checkValue : public exception { public: int initialvalue = 0; const char* what() const throw () { cout << "Incorrect value"; } }; int main() { int initialValue = 0; cout << "Enter integer value greater than zero "; try { cin >> initialValue; cout << initialValue; if (initialValue == 0) throw checkValue(); if (initialValue < 0) throw checkValue(); cout << "your value is " << initialValue; } catch (checkValue ex) { ex.what(); cout << ex.initialvalue; } return 0; }
Terminating program execution
exit()
Causes an immediate and orderly termination of a program without performing any regular cleanup tasks. It has the following prototype:
void exit(int status);
The value of status is returned as an exit code to the calling code. If this exit_code is 0 or EXIT_SUCCESS, a successful termination status is returned to the host environment. Any other value indicates that program termination is due to an error. The constant EXIT_FAILURE can also be used to indicate an unsuccessful termination.
In the code sample below an attempt is made to open a file. If that file does not exist the program execution is terminated
#include <stdio.h> /* for printf, fopen */ #include <stdlib.h> /* for exit, EXIT_FAILURE */ void test(){ printf ("Error opening file"); exit (EXIT_FAILURE); ) int main () { FILE * pFileName; pFileName = fopen ("somefile.txt","r"); if (pFileName ==NULL) { test(); } else { printf ("File opened successfully:\n"); } print ("the end"); return 0; }
quick_exit
Calls functions registered using at_quick_exit and then terminates the process normally by returning control to the host environment after calling all.
#include <stdio.h> /* needed for printf */ #include <stdlib.h> /*needed for at_quick_exit, quick_exit, EXIT_SUCCESS */ void fexit (void) { printf ("Quick exit function.\n"); } int main () { at_quick_exit (fexit); printf ("Start executions\n"); quick_exit (EXIT_SUCCESS); printf ("Main function block"); // this is never executed return 0; }
atexit
Automatically calls a function when a program terminates normally.
abort()
Causes immediate and abnormal program termination. It does not return any status information to the host environment, nor does it perform an orderly shutdown of your program.
assert()
Evaluates an Expression. If this expression evaluates to 0, this causes an assertion failure that terminates the program. It is normally used during debugging to capture programming errors and is disabled after the debugging phase.
#include <stdio.h> #include <assert.h> /* assert */ void fnAssert(int value) { printf ("exiting\n"); assert (value!=1); } int main () { printf ("start \n"); fnAssert(1); printf ("terminate"); return 0; }