Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Lecture 8 OOP Course. 9. Exceptions Error handling in C++ Error handling in C++

Similar presentations


Presentation on theme: "1 Lecture 8 OOP Course. 9. Exceptions Error handling in C++ Error handling in C++"— Presentation transcript:

1 1 Lecture 8 OOP Course

2 9. Exceptions Error handling in C++ Error handling in C++

3 Motivation There are several ways a function may react when encountering an unexpected/erroneous situation –Terminate the program Cannot be used in a program that cannot afford to crash –Return a value representing “error” –Raise a flag Many standard C library functions used global variable errno –Need to check the flag after every operation –Losses information –Call a function supplied to be called in case of error How will it handle the error? char* String::getString(); //ok: return NUKK on error int atoi(const char *); //what to return for “bad-str”?

4 The Challenge in Handling Errors There are circumstances in C++ where none of the aforementioned error reporting styles can work: –In constructors (no return value)‏ –In overloading operators –Error handling should release resources before leaving a scope (memory deallocation, closing files, etc.)‏ Rational r = (a + b)*(c + d / e);

5 The Challenge in Handling Errors The function that encountered an unexpected situation has no clue about an appropriate reaction, nor does that function that called it allThis is the case for all library functions The consequence is that an error-value should propagate through a series of function-calls

6 Introduction to Exception Handling exception An exception is any unusual event, either erroneous or not, detectable by either hardware or software, that may require special processing exception handling Without exception handling –When an exception occurs, control goes to the operating system, where typically an error message is displayed the program is terminated With exception handling –Programs are allowed to trap exceptions –There is a possibility to fix the problem and continuing execution

7 The Throw-Catch Game catch throw return call Error handling is a path parallel to the return path When a throw is activated stack unwinding occurs and destructors are activated If, during a throw, a destructor throws additional exception std::terminate() is called we cannot handle two exceptions

8 Example Lets consider class stack const int MAX_ELEM=10; template class Stack { Tm_arr[size]; intm_index; public: Stack() : m_index(0) {} void Push(T elemP) { m_arr[m_index] = elemP; m_index++;} T& Pop() { m_index--; return m_arr[m_index]; } int Index() const { return m_index; } };

9 Class Anomalies What happens if we pop() an empty stack? What happens if we push() on a full stack? We decide that these situations need to be handled in a special manner, since they are anomalies of the class behavior First we define classes of exceptions which may be thrown Upon anomaly detection, we will throw an exception class popOnEmpty { /* … */ } class pushOnFull { /* … */ }

10 Exception Handling Syntax Exception Handlers try { -- code that is expected to raise an exception } catch (formal parameter) { -- handler code }

11 Example Our code would now change No need to examine the returned value for checking for success.... void Push(T elemP) { if (m_index>=size)‏ throw pushOnFull(); // an object is throws m_arr[m_index] = elemP; m_index++;} T& Pop() { if (m_index<=0)‏ throw popOnEmpty(); // an object is thrown m_index--; return m_arr[m_index]; }... };

12 Try…Catch Blocks try {…} catch {…}Wrap the code which needs to be “exception sensitive”, and react to raised exceptions, in a try {…} catch {…} blocks The client’s code look now as following int main() { try{ Stack si; si.Pop(); si.Push(5); si.Pop(); } catch (popOnEmpty) { cout << "stack is empty !!" << endl; } catch (popOnFull) { cout << "stack is Full !!" << endl; } };

13 Try…Catch Blocks When exception is thrown, execution resumes in the “closest” catch clause handling the exception If no catch clause exists capable of handling the exception, program execution resumes at the terminate() function Variables declared within the try block cannot be referred to at the catch clause, since they are local to the block int main() { try{ Stack si; si.Pop(); // ERROR! cout << “This line will not be printed” << endl; si.Push(5); si.Pop(); } catch (popOnEmpty) { cout << "stack is empty !!" << endl; } cout << “Execution resumes here” << endl; };

14 Throwing Objects Why throw an object? –Additional data encapsulated –An object is created upon invoking the throw statement –Can be created with additional data, passed to Ctor –Object is destroyed after the catch clause ends

15 Stack Unwinding Up the chain of nested function calls, a suitable catch clause is searched for Upon functions and compound statements exit, stack is being unwound Lifetime of local variables ends Destructors are called terminate()If no handler is supplied, terminate() is called –Since exception is a situation, where the program cannot continue execution in a normal manner terminate()abort()‏ –By default terminate() calls abort()‏ Similar to function call behavior –But information to set up a function call is not available at compile time, run-time support is needed

16 Re-throwing and Catch All After some corrective action, a catch clause may throw an exception to be further handled, passing the exception to another catch clause, by throw void func() { try{ //code that might throw bad_alloc error } catch (bad_alloc e) { // do what can be done here throw; }

17 Re-throwing and Catch All General exception handling can be specified If specified with combination, must be specified last, since evaluation is evaluated in turn catch (popOnEmpty e) { // something } catch (popOnFull e) { // something } catch (…) { // handle every exception // something }

18 Exception Specification Function interface need to be as precise as possible, it is the contract between several codes Client code may need to prepare for specific handling Best is to provide exception specification with the method declaration –This will help the compiler to check consistency, to check that no other exceptions are thrown –It follows the function parameter list

19 Exception Specification //... void Push(T elemP) throw(pushOnFull) { if (m_index>=size)‏ throw pushOnFull(); // an object is throws m_arr[m_index] = elemP; m_index++;} T& Pop() throw(popOnEmpty) { if (m_index<=0)‏ throw popOnEmpty(); // an object is thrown m_index--; return m_arr[m_index]; } //... };

20 Nesting try Blocks Exceptions are always handled by closest matching handler try { throw 5; } catch (int x)‏ { cout << x << endl; // exception will be caught here } } catch (int x)‏ { cout << x-5 << endl; }

21 Exceptions from Function Calls No different from nested try blocks Auto variables on stack are destroyed Exception jumps to nearest handler Allows exception handlers to be implemented far away from where the problem was –May requires a knowledge of the issue packaged in exception object for appropriate handling

22 Exception Hierarchies Class types representing exceptions may be organized into groups or hierarchies class exception {} class stackExcp : public exception {} class popOnEmpty : public stackExcp {} class pushOnFull : public stackExcp {} Throwing an exception of type popOnEmpty may be caught by a handler expecting its base Therefore order should be handling more concrete types, and then handling more generic types –Since handling is evaluated in order of specification, “first match” Ctors and Dtors are called in order like before

23 Standard Exception

24 class exception { public: exception(); exception(const char * _what); virtual ~exception(); // Returns a C-style character string describing // the general cause of the current error virtual const char* what() const; //... }; exception Standard library exception class exception presented in

25 Exceptions in Constructors Destructors only called for fully constructed objects –Sub-objects (member variables that are objects) will get destroyed –If memory allocated dynamically in constructor, it could get lost Exceptions are automatically re-thrown from constructors String::String(char const * other)‏ try : length(strlen(other), str(stcpy(other, new char[length+1]) {} catch(std::bad_alloc& e) { cerr << e.what(); throw; }

26 Exceptions Example A programmer-define ListException class #include using namespace std; class ListException: public exception{ public: ListException (const string& message = “”)‏ : exception(message.c_str()){} }; // end ListException

27 1 // A simple exception-handling example that checks for 2 // divide-by-zero exceptions 3 #include 4 #include 5 using namespace std; 6 7 // DivideByZeroException objects should be thrown by 8 // functions upon detecting division-by-zero exceptions 9 class DivideByZeroException : public exception { 10 11 public: 12 13 // constructor specifies default error message 14 DivideByZeroException() 15 : exception( "attempted to divide by zero" ) {} 16 17 }; // end class DivideByZeroException Define new exception class (inherit from exception ). Pass a descriptive message to the constructor. Exceptions Example

28 18 // perform division and throw DivideByZeroException object if // divide-by-zero exception occurs double quotient( int numerator, int denominator ) throw 1(DivideByZeroException ){ 22 // throw DivideByZeroException if trying to divide by zero 23 if ( denominator == 0 )‏ 24 throw DivideByZeroException(); // terminate function 25 26 // return division result 27 return static_cast ( numerator ) / denominator; 28 } // end function quotient 29 30 int main()‏ 31 { 32 int number1; // user-specified numerator 33 int number2; // user-specified denominator 34 double result; // result of division 35 36 cout << "Enter two integers (end-of-file to end): "; 37 If the denominator is zero, throw a DivideByZeroException object Exceptions Example

29 38 while ( cin >> number1 >> number2 ) { 39 // try block contains code that might throw exception 40 // and code that should not execute if an exception occurs 41 try { 42 result = quotient( number1, number2 ); 43 cout << "The quotient is: " << result << endl; 44 } // end try 45 // exception handler handles a divide-by-zero exception 46 catch ( DivideByZeroException ÷ByZeroException ) { 47 cout << "Exception occurred: " 48 << divideByZeroException.what() << endl; 49 } // end catch 50 51 cout << "\nEnter two integers (end-of-file to end): "; 52 } // end while 53 cout << endl; 54 return 0; 55 } // end main Exceptions Example catch (exception& e) { cout << “Exception occurred: “ << e.what() << endl; }

30 Enter two integers (end-of-file to end): 100 7 The quotient is: 14.2857 Enter two integers (end-of-file to end): 100 0 Exception occurred: attempted to divide by zero Enter two integers (end-of-file to end): ^Z Exceptions Example

31 When To Use Exceptions Fix the problem and try again Patch the problem and continue Make a complex error mechanism simpler Make code safer (catch fatal errors)‏

32 10. STL: The C++ Standard Library

33 STL – Why? Reuse. –Reusable core components –The programmer can focus on application development, and rely on for portability of components such as: strings, containers, algorithms (sort, search, etc.) and I/O streams STL had been designed with efficiency in mind This lecture will be only an overview…

34 STL Overview templatesFor best Generality and Reusability, most of STL ’s components are supplied as templates (functions and classes)‏ Three main component groups: –Containers –Containers - contain and organize other objects –Iterators –Iterators - provide a means of sequencing through the elements of a container in some order –Algorithms –Algorithms - perform certain operations on containers’ elements. –Those components are independent of each other, pluggable, and exchangeable, through generic interface

35 Containers – Overview An STL container is an object that manages a collection of elements –Different containers, with efficiency considerations For search, operator== is required For ordering, relational operators are needed, i.e. operator< is required –With common, generic interface –Also, default constructor, copy constructor, copy assignment operator and destructor are needed Sequence containers - Ordered collection Associative containers – fast retrieval

36 Containers – Overview

37 Sequence Containers –vector –vector – dynamic array Fast insertion at end, and allow random access Should be your default choice, but choose wisely Backward compatible with C : &v[0] points to the first element –deque –deque – double-ended queue Offers random access, back and front insertion Slower than vectors, no C compatibility –list –list – 'traditional' doubly linked list Fast insertion anywhere, but provide only sequential access –string –string – yes, it is a STL container (a typedef actually)‏ –etc.

38 Associative Containers –The sorting criterion is also a template parameter –set –set – add and delete elements, no duplicates –multiset –multiset – you can have several copies of the same element (these are often called bags) –map –map – separate key and value, no duplicates –multimap –multimap – map allowing duplicate keys –etc.

39 Containers Common Functionality Common member functions for all STL containers: –empty – returns true if there are no elements in the container, otherwise returns false –size – returns the number of elements currently in the container –max_size – returns the maximum number of elements for a container –erase – erase one or more elements from the container –clear – erase all elements from the container –swap – swaps the elements of two containers

40 List Example #include #include using namespace std; int main() { list coll; // list container for character elements // append elements from 'a' to 'z' for (char c='a'; c<='z'; ++c) { coll.push_back(c); } /* print all elements * - while there are elements * - print and remove the first element */ while (! coll.empty()) { cout << coll.front() << ' '; coll.pop_front(); } cout << endl; }

41 Iterators The containers provide iterator classes, enabling element iteration and access functionality in a common and general interface Used as arguments to algorithms Containers provide several iterators –Begin, End, Reverse Begin, Reverse End 5 categories – each has specific operations –Input, Output, Forward, Bidirectional, Random

42 Iterators Iterators are similar to pointers –point to element in a container –iterator operators uniform for all containers * dereferences, ++ advances pointer container.begin() returns iterator pointing to first element container.end() returns iterator pointing after last element for(it = c.begin(); it != c.end(); it++)‏ {... } it

43 Iterator Categories All iterators: p++, ++p Input iterators: v = *p, p1 = p2, p1 == p2, p1 != p2 Output iterators: *p = v, p1 = p2 Forward iterators: all above Bidirectional iterators: p--, --p Random access iterators: p+=i; p-=i, p+i, p-i,,…

44 Vector Example #include #include #include using namespace std; int main() { vector vString; vString.push_back(“Avraham“); vString.push_back(“Isaac“); vString.push_back(“Yaakov“); cout ::const_iterator ci; for(ci=vString.begin();ci!=vString.end();ci++)‏ cout ::reverse_iterator ri; for(ri=vString.rbegin();ri!=vString.rend();++ri) cout << *rii << endl;

45 Algorithms Overview Algorithms are designed to be a “plug-in” to work on any container Search algorithms –find, find_if, count, count_if, search, binary_search, etc. Sorting algorithms –sort, merge, partition, etc. Other modifying sequence algorithms Relational & minimum / maximum algorithms More…

46 Find Example int main()‏ { list lInt; INSERT_ELEMENTS(lInt,1,9); INSERT_ELEMENTS(lInt,1,9); PRINT_ELEMENTS(lInt,"coll: "); // find first element with value 4 list ::iterator pos1; pos1 = find (lInt.begin(), lInt.end(), 4); // find second element with value 4 // note: continue the search behind the first 4 (if any) list ::iterator pos2; if (pos1 != lInt.end())‏ pos2 = find (++pos1, lInt.end(), 4); // print all elements from first to second 4 (both included) //note: now we need the position of the first 4 again (if any) //note: we have to pass the position behind the second 4 (if any) if (pos1!=lInt.end() && pos2!=lInt.end()) { copy (--pos1, ++pos2, ostream_iterator (cout," ")); cout << endl; } } INSERT_ELEMENTS INSERT_ELEMENTS and PRINT_ELEMENTS PRINT_ELEMENTS define elsewhere

47 Interconnectivity of Components The connections between iterators, containers and algorithms: –Containers provide iterators as part of their interface –Algorithms are defined in terms of iterators There is no direct connection between algorithms and containers The use of iterators enables writing generic algorithms which are applicable to any container class that provides a standard iterator Container of T Iterator generates uses Generic Algorithm

48 More about STL B. Stroustrup, The C++ Programming Language –Part III (427-657)‏ STL examples –http://www.josuttis.com/libbook/toc.htmlhttp://www.josuttis.com/libbook/toc.html STL tutorials –just hit Google with "STL Tutorial"


Download ppt "1 Lecture 8 OOP Course. 9. Exceptions Error handling in C++ Error handling in C++"

Similar presentations


Ads by Google