Exception Handling in C++

I'm relearning the C++ Programming, so please ignore all my coding errors. 

Let's get started. As C doesn't provide support to error handling or exception handling, it is the responsibility of the programmer to prevent the errors at first place and test the return values from the functions.  

Exception is a response to exceptional circumstance that arises while a program is running such as an attempt to divide by zero. It is basically an error which should not occur, but when the error occurred, this needs to be informed to the  computer. 

In other words, an exception is an error that will cause the program to exit the current iteration of whatever loop it is in. 

Exceptions work by first making a "try" block, and following this with one or more "catch" blocks. If a "throw" is executed from inside the "try" block, it will exit the "try" block and search for a relevant "catch" block to tell it what to do. In general, if there are multiple catch blocks, they will each deal with a different type of exception. 

If we need to catch the errors of the program, the program needs to be written in the try block. 

To identify the errors, statement throw is used. 

throw <error-no/integer>                                         

//String Exception 

void function ()
{
   throw "string"
}

try {
   function();
} catch (string str) { }

//Built-in exceptions 

void function ()
{
   throw invalid_argument("Negative depth is not accepted.");
}

try {
   function();
} catch (const std::invalid_argument& e) { }

Note: In the second example, you throw a function name as invalid_argument, so while stating that in catch, you need to have invalid_argument& 

Catch statement allows a block of code to be executed if an error occurs in the try block. If there is no error in the try block, the catch block is skipped altogether.

Simple exception handling code is available here as well to try it yourself. 

#include <iostream>

using namespace std;

int main()
{
    int MomAge = 34;
    int SonAge = 56;
    
    try {
        
        if (SonAge > MomAge) {
           throw 99;         
        } 
       
    } 
    catch (int x) {
        cout << "Son's age is greater than Mom's, and the error returned is " << x << endl;
    }
    
    MomAge = 56;
    //To handle any type of exception, use three dots (...) syntax inside the catch block. 
    try {
        
        if (SonAge == MomAge) {
           throw 99;         
        } 
       
    } 
    catch (...) {
        cout << "Son's age is as same as mom's age " << endl;
    }
    
    return 0;
}

Output:

1
2
Son's age is greater than Mom's, and the error returned is 99
Son's age is as same as mom's age 

We can also have two catch statements fro a single try {}

#include <iostream>

using namespace std;

int main()
{
int SonAge = 56;

//To handle any type of exception, use three dots (...) syntax inside the catch block.
try {
if (SonAge == 56) {
throw 99;
}
}
/* Standard exceptions, logic_error, invalid_argument
domain_error, length_error
out_of_range, future_error (since C++11)
runtime_error, range_error
overflow_error, underflow_error
regex_error (since C++11), system_error (since C++11)
ios_base::failure (since C++11), filesystem::filesystem_error (since C++17)
tx_exception (TM TS), nonexistent_local_time (since C++20)
ambiguous_local_time (since C++20), format_error (since C++20)
bad_typeid, bad_cast, bad_any_cast (since C++17)
bad_optional_access (since C++17), bad_expected_access (since C++23)
bad_weak_ptr (since C++11), bad_function_call (since C++11), bad_alloc,
bad_array_new_length (since C++11), bad_exception,
ios_base::failure (until C++11), bad_variant_access (since C++17)*/
catch (const std::exception& ex) {
std::cout << "caught exception " << std::endl;
}
catch (...) {
cout << "Son's age is as same as mom's age " << endl;
}
return 0;
}

Output:

1
Son's age is as same as mom's age 

Advantages

Useful especially when allocating memory. 

Shirleys-MacBook-Air:CPProgramming shirley$ cat bad_alloc.cpp
#include <iostream>

int main()
{
    char* c = new char[40000000000000U];
}
Shirleys-MacBook-Air:CPProgramming shirley$ g++ -o bad bad_alloc.cpp 
Shirleys-MacBook-Air:CPProgramming shirley$ ./bad
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted

Why exceptions terminate the program?

Exceptions will not always terminate the program unless it is not handled.

What happens when exception is thrown?

  • The program control climbs up the call stack.
  • Every local scope is closed, and all destructors are called. 
  • If an appropriate catch is reached, it handles the error. Then program resumes from the next line of the catch block or the next line of the throw statement. 

What happens if an exception is not caught?
  • Stack unwinding occurs. 
  • Uncaught exception is permitted to terminate the program without invoking any destructors. 
  • But, if an exception is thrown, no code after the try block will be executed unless the exception is not caught. 

Note: Do not throw an exception in destructors. 


Disabling exceptions

The program needs to be compiled with g++ -fno-exceptions <cpp file> to disable the exceptions. So, the application will not be terminated if the exceptions are uncaught. 

By default, exceptions are enabled using -fexceptions.

I'm trying to make a note of all single details. So, here is one!!

Namespace is a declarative region that provides a scope to the identifiers inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries. 



References

Exception with variable messages



Comments