Exception Handling

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 20

Chapter – 6

Exception Handling
Exception handling: Introduction, C-Style Handling of Error-generating Code, C++ Style
Solution - the try/throw/catch Construct.
Overview of Error and Exception:
Errors are the problems that occur in
the program due to an illegal operation performed by the user or by the fault
of a programmer. Errors are also termed as bugs or faults. Errors can stop
normal flow of program execution, produce inaccurate results, or even cause
the program to crash.
Effective error handling is essential for addressing these errors and ensuring
the program's stability and dependability. The errors can be broadly
categorized into three main types: syntax errors, runtime errors, and logic
errors.

 Compile time errors


 Runtime errors
 Logical errors
Compile Time Errors:
Those errors that are caught (occurred) during
compilation time called as Compile Time Errors. Some of the most common
compile-time errors are syntax errors, library references
error, incorrect import of library functions and methods error, uneven bracket
pair(s), etc.
Syntax Errors: Every language has a set of syntax rules that stipulate
(specify) the right way to write code in that language. Syntax errors occur
when a code violates the rules of the programming language's syntax.
Syntax error also known as compile-time errors.
Compile time (syntax) errors prevent the code from being successfully
compiled. Examples of syntax errors include missing semicolons,
mismatched parentheses, incorrect variable names, etc.

The compiler usually provides specific error messages pointing to the


location of the syntax error in the code.
Example:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello Scaler Topics!"
return 0;
}
Output:
test.cpp: In function 'int main()':
test.cpp:5:35: error: expected ';' before 'return'
cout << "Hello Scaler Topics!"
^
;
test.cpp:8:5:
return 0;
As we can see the compiler detected the compilation error, i.e. missing
semi-colon.
Run-Time Errors:
Those errors that cannot be caught during compilation
time but caught (occur) in run time called as Run-Time Errors. As we cannot
check these errors during compile time, i.e. the compiler does not catch
these errors; instead, they are detected during the execution of the program.
The program might crash, terminate abnormally, or produce incorrect results
when a runtime error occurs.
The runtime error arises due to unexpected input, incorrect file operations,
division by zero, accessing an out-of-bounds array index, or other situations
where the program's behavior is not well-defined.

Example:
#include <iostream>
using namespace std;
int main() {
int a = 5;
// Dividing the number a by zero, so the program will compile easily
// but run time error will be generated.
cout << a / 0;
return 0;
}
Output:
test.cpp: In function 'int main()':
test.cpp:11:14: warning: division by zero
cout << a / 0;
~~^~~
Logic Errors:
Logic errors occur when the code compiles and runs without
errors but does not produce the expected or desired output. These errors can
be tricky to identify because the program behaves as intended, but the
outcome is incorrect due to errors in the logical flow or calculations in the
code. Logic errors often require careful debugging and code inspection to
identify and fix.
Example:
int main() {
int radius = 5;
double area = 3.14 * radius * radius; // Incorrect formula for calculating
area of a circle
cout << "The area is: " << area << endl;
return 0; }
What is Exception?
Exceptions are also called as run-time errors, is an abnormal condition
that a program may encounter during program execution. Many a time, your
program looks error-free during compilation. But, at the time of execution
(runtime), some unexpected errors or unwanted
events or objects occurred (come to the surface), and the program prints
an error message and stops executing. Such unexpected happenings are
called exceptions.

Example:
int a = 8/0;
In the above example, the program will show an error during runtime
because dividing by zero is undefined.
Exceptions occur for numerous reasons, including invalid user input, code
errors, device failure, the loss of a network connection,
insufficient memory to run an application, a memory conflict with another
program, a program attempting to divide by zero operation, a program
attempting to Access to an array out of its bounds or a user attempting to
open files that are unavailable.
What are the types of exceptions?
Similar to errors, exceptions are also
of two types. They are as follows:
 Synchronous exceptions: The exceptions which occur during the
program execution due to some fault in the input data. For example:
Errors such as out of range, overflow, division by zero
 Asynchronous exceptions: The exceptions caused by events or
faults unrelated (external) to the program and beyond the control of
the program. For Example: Key board failures, hardware disk failures
Exception Description
std::exceptio It is an exception and parent class of all
n standard C++ exceptions.
std::logic_fail It is an exception that can be detected by
ure reading a code.
std::runtime_ It is an exception that cannot be detected by
error reading a code.
std::bad_exce It is used to handle the unexpected exceptions
ption in a c++ program.
std::bad_cast This exception is generally be thrown
by dynamic_cast.
std::bad_type This exception is generally be thrown
id by typeid.
std::bad_alloc This exception is generally be thrown by new.

Difference between Error and Exception:


What do you mean by Exception Handling?
Exception handling is the process of handling
errors and exceptions to avoid the disrupt of the normal operation of a
program. Using the exception handling mechanism, the control from one part
of the program where the exception occurred can be transferred to another
part of the code.
Keywords for Exception Handling:

try: The block of code defined under this statement is being tested for
runtime errors (The keyword try is used to preface a block of statements
which may generate exceptions). If exceptions occur that may throw.
Syntax of try statement:
try
{
statement 1;
statement 2;
}
throw: When an exception is detected, it is thrown using a throw statement
in the try block. It means, transfers control to the nearest catch block that
matches the type of the thrown exception, enabling error handling.
Syntax of throw statement
 throw (excep);
 throw excep;
 throw; // re-throwing of an exception
catch: A catch block defined by the keyword ‘catch’ catches the exception
and handles it appropriately. The catch block that catches an exception must
immediately follow the try block that throws the exception.
catch(Exception_name exception_1)
{
// code to handle exceptions
}
Complete syntax:
try
{
// protected code
throw exception;
}
catch(Exception_name exception_1)
{
// code to handle exceptions
}
The Exception_name is the name of the exception to be caught. The
exception_1, is defined names. They are referring to the exceptions.
Every try block is followed by the catch Block. The throw Statement throws
an exception, which is caught by the catch block. The catch block cannot be
used without the try block.
As soon as an exception is found, the throw statement inside the try block
throws an exception (a message for the catch block that an error has
occurred in the try block statements). Only errors occurring inside the try
block are used to throw exceptions. The catch block receives the exception
that is sent by the throw block. The general form of the statement is as per
the following figure.

Example: Program to divide two numbers and throw an exception if


the divisor is 0
#include <iostream>
using namespace std;
int main()
{
float numerator, denominator, result;
numerator = 9;
denominator = 0;
try
{
// throw an exception if denominator is 0
if (denominator == 0)
throw 0; // Throwing an integer
result = numerator / denominator; // if denominator not
zero
cout << numerator << " / " << denominator << " = " << result <<
endl;
}
catch (int exception)
{ // Catching an integer
cout << "Error: Cannot divide by " << exception << endl;
}
return 0;
}
 In the above code, we have put the result = numerator /
denominator in the try block because this statement must not be
executed if the denominator is 0. If the denominator is 0, the
statements after the throw statement in the try block is skipped.
 The catch block catches the thrown exception as its parameter and
executes the statements inside it.
 Here, the exception is of type int. Therefore, the catch statement accepts
a int parameter.
 If there isn't any exception thrown, the catch block gets skipped.
Output: Error: Cannot divide by 0
You can also use the throw keyword to output a reference number, like a
custom error number/code for organizing purposes:
#include <iostream>
using namespace std;
int main()
{
int numerator, denominator, result;
numerator = 8;
denominator = 0;
try
{
if (denominator == 0) // Throw an exception if the denominator is 0
throw 505; // Throwing an integer
result = numerator / denominator; // If the denominator is not
zero
cout << numerator << " / " << denominator << " = " << result <<
endl;
}
catch (int myNum)
{ // Catching an integer
cout << "Error: Cannot divide by " << myNum << endl;
}
return 0;
}
Output: Error: Cannot divide by 505
/* Write a program to illustrate division by zero exception. */
#include <iostream>
using namespace std;
int main()
{
int a, b;
cout<<"Enter the values of a and b"<<endl;
cin>>a>>b;
try{
if(b!=0)
cout<<a/b;
else
throw b;
}
catch(int i)
{
cout<<"Division by zero: "<<i<<endl;
}
return 0;
}
Output:
Enter the values of a and b
2
0
Division by zero: 0
/* Write a program to illustrate array index out of bounds exception.
*/
#include <iostream>
using namespace std;
int main() {
int a[5]={1,2,3,4,5},i;
try{
i=0;
while(1){
if(i!=5)
{
cout<<a[i]<<endl;
i++;
}
else
throw i;
}
}
catch(int i)
{
cout<<"Array Index out of Bounds Exception: "<<i<<endl;
}
return 0;
}
Output:
1
2
3
4
5
Array Index out of Bounds Exception: 5
Handling All Types of Exceptions (...)
Suppose we do not know the types
of exceptions that can occur in our try block or the throw type used in the try
block; then, we can use the ellipsis symbol as our catch parameter. catch
(...) is known as the catch-all exception handler.
Syntax
try
{
// code to check exceptions
}
catch (...)
{
// code to handle exceptions
}
Example
#include <iostream>
using namespace std;
int main()
{
float numerator, denominator, result;
numerator = 9;
denominator = 0;
try
{
// throw an exception if the denominator is 0
if (denominator == 0)
throw 0;
result = numerator / denominator; //if denominator not zero
cout << numerator << " / " << denominator << " = " << result << endl;
}
catch (...)
{
cout << "Error: Cannot divide by " << endl;
}
return 0;
}
Output: Error: Cannot divide by
Multiple catch Statements:
This is like an if else-if ladder. It is also
possible that a program segment has more than one condition to throw an
exception. In such cases, we can associate more than one catch statement
with a try (similar to switch statement) (we can use
multiple catch statements for different kinds of exceptions that can occur
from a single block of code in the try block).
The format of multiple catch statements is as follows:
try
{
// try block
}
catch (type1 arg)
{
// catch section1
}
catch (type2 arg)
{
// catch section2
}
.......
.......
catch (typen arg)
{
// catch section-n
}
When an exception is thrown, the exception handlers are searched in the
order for an appropriate match. The first handler that yields a match is
executed. After executing the handler, the control goes to the first statement
after the last catch block for that try. When no match is found the program
will terminate.
/*Write a C++ program to throw multiple exceptions and define
multiple catch
statement. */
#include <iostream>
using namespace std;
void num (int k)
{
try
{
if (k==0) throw k;
else
if (k>0) throw 'P';
else
if (k<0) throw Q;
cout<<"*** end of try block ***\n";
}
catch(char g)
{
cout<<"Caught a positive value \n";
}
catch (int j)
{
cout<<"caught an null value \n";
}
catch (double f)
{
cout<<"Caught a Negative value \n";
}
cout<<"*** end of try catch ***\n \n";
}
int main()
{
cout<<"Demo of Multiple catches"<<endl;
num(0);
num(5);
num(-1);
return 0;
}
Output:
Demo of Multiple catches
caught an null value
*** end of try catch ***
Caught a positive value
*** end of try catch ***
Caught a Negative value
*** end of try catch ***
Caught a positive value
*** end of try catch ***
The Exception_name is the name of the exception to be caught. The
exception_1, is defined names. They are referring to the exceptions.
 Here, our program matches the type of exception that occurred in
the try block with the catch statements.
 If the exception that occurred matches any of the
normal catch statements, that particular catch block gets executed.
 If the exception occurred, it matches none of the
normal catch statements, the catch-all exception handler, catch (...) gets
executed.
 The catch (...) statement acts as the default catch statement. Therefore,
it must always be the final block in the try...catch statement
 It is not necessary to have a default catch block in the program.
Example
#include <iostream>
using namespace std;
int main()
{
float numerator, denominator, arr[] = {1, 2, 3, 4, 5};
int index;
cout << "Enter array index: ";
cin >> index;
try
{
// throw exception if array is out of bounds
if (index >= sizeof(arr))
throw "Error: Array out of bounds!";
// not executed if array is out of bounds
cout << "Enter numerator: ";
cin >> numerator;
cout << "Enter denominator: ";
cin >> denominator;
// throw exception if denominator is 0
if (denominator == 0)
throw 0;
// not executed if denominator is 0
arr[index] = numerator / denominator;
cout << arr[index] << endl;
}
// catch "Array out of bounds" exception
catch (const char* msg)
{
cout << msg << endl;
}
// catch "Divide by 0" exception
catch (float num)
{
cout << "Error: Cannot divide by " << num << endl;
}
// catch any other exception
catch (...)
{
cout << "Unexpected exception!" << endl;
}
return 0;
}
In the above code, we are dividing two numbers and storing their result in
an array arr at the index value given by the user. There can be two possible
exceptions here:
 Array index out of bounds: the indexvalue given by the user is greater
than the size of the array
 Divide by 0: If the denominator is 0.
If there occurs any other exception in the try block, it will be caught by
the catch(...) statement.
Output
If the user enters a valid input.
 Enter array index: 3
 Enter numerator: 10
 Enter denominator: 2
5
If the user inputs an invalid index
 Enter array index: 5
Error: Array out of bounds!
If the denominator is 0
 Enter array index: 2
 Enter numerator: 8
 Enter denominator: 0
Error: Cannot divide by 0
If any unexpected exception occurs
 Enter array index: 2
 Enter numerator: "sScholarHat" // Entering a string instead of a number
Unexpected exception!
Why is Exception Handling used in C++?
The main advantages of exception handling over traditional error handling
are given below.
1. To distinguish the error handling code from the normal code: In
traditional error handling, we always use if and else statements to handle
the errors. These traditional error handling codes get mixed up with the
normal code. This makes code less readable and maintainable. We use
exception handling over traditional error handling to get rid of these
problems.
2. A function can handle any exception they choose: In C++, a
function can identify the exceptions that it throws with the help of the
throw keyword. The caller of this function will handle the uncaught
exception either by specifying it again or catching it.
3. Grouping of Error Types: We use exception handling to create a
hierarchy of exception objects, group exceptions in namespaces or
classes, categorize them according to types.o

You might also like