INTRO TO COMPUTER SCIENCE II
EXCEPTIONS
CS162
Error Handling
Syntax errors – when statement is wrong according to C++ grammar
Usually caught by compiler, so we don’t worry about these much
Semantic errors – when a statement’s syntax is correct, but doesn’t do what the programmer intended
Not caught by compiler, so may not show up, cause wrong output, corrupt data, program crash, etc.
Logic errors – programmer incorrectly codes the logic of a statement
Violatedassumptions–programmerassumes something will be true or false, but it isn’t
//incorrect syntax
if 5 is not equal to 6 then write “no t equal”;
//correct syntax
if (5 != 6)
cout << "not equal";
//logic error
if (x >= 5)
cout << “x is greater than 5”
//possible violated assumption
string hello{"Hello, world!"};
cout << "Enter an index: ";
int index;
cin >> index;
cout << "Letter #" << index << " is " << hello[index] << '\n';
Defensive Programming
Design your program to identify where assumptions might be violated and write code to detect and handle it in a predictable way
Detecting errors
Check that parameters have appropriate values at the top of each function
Check the return value and error reporting mechanisms after a function has returned
Check user input to make sure it meets the expected formatting or range
Defensive Programming
Handling errors
No best way – depends on the problem Some methods
Skip code that depends on assumption being valid
If in a function, return an error code back to caller and let caller deal with it (e.g. return -1)
Use exit() function to terminate program immediately and return an error code to the OS
This can lead to Valgrind errors though!
If user enters invalid input, ask user to enter input again
Use cerr or clog output streams to write error messages on the screen (or redirect to a file)
Use an assert statement
Assert
Evaluatesaconditional(trueorfalse) at runtime
If true, does nothing
If false, displays an error message and program
is terminated
#include
Often used for checking parameters are valid, and if return values are valid
Error message contains the conditional that failed, along with the name of the file and the line number
#include
int getValue(const array
{
assert(i >= 0 && i <= 9);
return a[i];
}
//call function with invalid index
int value = getValue(array, -3);
Assertion failed: i >= 0 && i <= 9, file C:\\prog.cpp, line 10
Exceptions
Not your typical error handling
Why do we need them?
Returncodescanbycryptic
Functionsonlyreturnonevalue,socan’treturntheresultandanerrorcodeatthesametime Somefunctionscan’t/don’treturnanything(constructors)
Functioncallersmaynotbeequippedtohandleerrorcodes
Exception handling lets us decouple error handling from control flow of code
Meant for dealing with unusual circumstances, save it for edge cases
Handlingbadinputyoucanpredictwillbecommonshouldnotuseexceptions
Examples:Nopermissionsforfileaccess,corruptedinputfiles,computerlowonmemory, hard drive ran out of space during file writing, etc...
Exceptions - Vocabulary
Looking for exceptions
Keywordtry
Tryblockslookforanyexceptionsthatarethrownbystatements within the block
Theydon’tdefinehowtheexceptionishandled,justgrabthem
Throwing exceptions
Keywordthrow
Throwstatementssignalthatanexceptionhasoccurredthat needs to be handled
Handling exceptions
Keyword catch
Catchblocksarewhereyouputthecodetohandlethe exceptions found by the try blocks
Try-throw-catch Syntax
try {
// this is where you place the code that might throw an exception
// if an exception is thrown, the try block will immediately halt execution
// and the catch block(s) will begin to execute
} catch (type_of_exception) {
// code to handle the exception
} catch (some_other_type_of_exception) { // code to handle the exception
}
Exceptions
If no exception is thrown, catch blocks are ignored
Catch blocks can print an error, return a value or error code, or throw another exception
Can catch multiple types of exceptions, just have more catch blocks
catchblocksgetexecutedinorderof appearance
So put more specific exceptions first
Common to define specialized exception class
Can create your own or use the generic C++
haveyourowninheritfromC++exception SeeSwim_Exceptionclassindemocode
//examples of different types of throws
throw -1;
throw ENUM_INVALID_INDEX;
throw “Can’t take sqrt of negative num”;
throw dX;
throw MyException(“Fatal Error”);
int main(){
try{
throw -1;
}catch(int x){
cerr << “Caught int exception” << x;
}catch(double){
cerr << “Caught double exception”;
}catch(const string &str){
cerr << “Caught string exception”;
}
return 0; }
Exceptions in Functions
Throw statements do not have to placed directly inside a try block
Usually throw in one function, and catch in another
Makes code more modular, as the caller function can handle the exception in different ways
Useful in member functions
Operators, constructors, etc.
Doesn’t require a change to function signature
double Sea_Otter::predict_swim_time(int distance) {
if (swim_speed == 0) {
throw swim_speed;
return distance/swim_speed; }
try {
int d = 30;
cout << tso1.predict_swim_time(d) << endl;
cout << "Everything was executed!" << endl; } catch (double e_val) {
cout << “Double exception " << e_val << endl; }
}
Exceptions
Uncaught exceptions
If a thrown exception is never caught, the program terminates and the OS will tell you that you had an unhandled exception
Catch-all handlers
Works like a normal catch block, but uses
ellipses operator instead of specifying a certain type to catch
Should be placed last in the catch block chain
int main(){
try{
float f = 1.0f;
throw f;
}catch(int x){
cerr << “Caught int exception” << x;
}catch(double){
cerr << “Caught double exception”;
}catch(const string &str){
cerr << “Caught string exception”;
}catch(...){
cerr << “Unknown exception”;
return 0; }
Exception Specifier – noexcept
Allow us to use a function declaration to specify whether or not a function will throw exceptions
Useful for determining whether a function call needs to be put inside a try block or not
Noexcept
indicates a function should not throw an exception, added in C++ 11
“no fail or no-throw guarantee”
Doesn’t actually stop a function from throwing an exception
But if one does get thrown, calls std::terminate because it was “unexpected”
void functionC(); //treat all exceptions as expected void functionD() noexcept; //all exceptions are unexpected
Exception Classes
Basic data types as exception types are vague
Use exception classes to handle exceptions from
various sources differently
A normal class designed specifically to be thrown as an exception
Exception handlers should catch exception class objectsbyreference
Inheritance
Exception handlers will match classes of a specific type, but also classes derived from that type
class Base{
public:
Base() {} };
class Derived : public Base{
public:
Derived() {}
};
int main() {
try {
throw Derived();
} catch (Derived &derived) {
cout << "caught Derived";
} catch (Base &base) {
cout << "caught Base";
}return 0; }
std::exception
Interface class designed to be a base class to any exception thrown by C++ standard library
what()
virtual member function returns C-style string description of exception
Derivedclassesoverrideitto change message appropriately
include noexcept specifier in C++11
#include
#include
int main() {
try {
// Your code using standard library goes here
// We’ll trigger one of the exceptions std::string s;
s.resize(-1); // will trigger a std::bad_alloc
} catch (std::exception &exception) {
// This will catch exception and all derived exceptions too cerr << "Standard exception: " << exception.what() << endl;
}
return 0; }
Exception Classes
//swim_exception.h #ifndef SWIM_EXCEPTION_H #define SWIM_EXCEPTION_H #include
class Swim_Exception : public exception { private:
//swim_exception.cpp #include
// define a constructor that sets the following variables: // name – name of the swimming animal
// description – explanation of the exception
Swim_Exception::Swim_Exception(string name, string tmp) : name(name), description(tmp) {
}
const char* Swim_Exception::what() const noexcept {
string error_message = name + ” encountered a critical exception: “; error_message += description;
return error_message.c_str();
}
string name;
string description; public:
Swim_Exception(string, string);
const char* what() const noexcept; };
#endif