Download presentation
Presentation is loading. Please wait.
1
Plab – Tirgul 8 Exceptions
2
Error handling in C Up to now we handled our errors in the “C way”: assert return codes global error variable ( errno and perror ) “The problem with C’s approach to error handling could be thought of as coupling—the user of a function must tie the error-handling code so closely to that function that it becomes too ungainly and awkward to use ”
3
Exceptions C++ introduces the use of exceptions to handle errors. You are already familiar with exceptions in Java. Unfortunately, in C++, due to the more complex memory model, the exceptions are far less simple .
4
Exceptions – why? Exceptions are used in C++ for: –Handling errors in constructors. –Handling memory errors. –Math errors. –Library errors or third party code.
5
Throwing exception example If pop() from empty ChangesCollection is illegal we would like to throw an exception. const Change* ChangesCollection::pop() { if (isEmpty()) throw 0;... } In C++ anything can be thrown: basic types (int, double, etc.), pointers, objects, references.
6
Throwing exception const Change* ChangesCollection::pop() { if (isEmty()) throw EmptyCollectionE(__FILE__, __LINE__);... } It’s a good practice to define special exception classes (usually there will be a hierarchy of these): If an exception is not caught it will abort the program. Unlike Java you will get no info about the exception (such as where it was thrown, the call stack).
7
Catching an exception We use try and catch similarly to Java. Consider: try {... } catch (CollectionE& e) { e.printErrorMessage(); throw; // re-throw the exception } Note that catching by reference enables polymorphism.
8
Catching an exception cntd. We can catch several different exceptions at a time: try {... } catch (EmptyCollectionE& e) {... } catch (CollectionE& e) {... } catch (...) { // catch ANY exception... } Note the order of the catch clauses
9
Re-Throw Having caught an exception, it is common for a handler to decide that it can’t completely handle the error. In that case, the handler typically does what can be done locally and then throws the exception again.
10
Re-Throw void h() { try { … } catch (Matherr){ if(can_handle_it_completely) { … return; } else { //do what can be done here. throw; // re-throw the exception. }
11
Grouping of Exceptions Exceptions fall naturally into families. This implies that inheritance can be useful to structure exceptions and to help exception handling: class Matherr {}; class Overflaw : public Matherr{}; class Underflow : public Matherr{}; Class Zerodivide : public Matherr{};
12
Grouping of Exceptions Cont void f() { try { // … } catch (Overflaw) { //handle Overflaw or anything derived from // Overflaw } catch (Matherr) { //handle any Matherr that is no Overflaw }
13
Exception specification Unlike Java, functions (methods) do not have to declare what exceptions they can throw: –int f(); // can throw any exception Still, it’s a good style to declare the exceptions your functions may throw: –int f() throw (BadArg, int*); // f can throw only BadArg, int* This function does not throw exceptions: –void g() throw();
14
Stack unwinding When exception is thrown all automatic variable of the function on the stack are freed. What about other resources, like: –open files –memory on heap FILE* f = fopen(filename, “r”); try {... } catch(...) { fclose(f); throw; } fclose(f); Note that in most C++ compilers there is no finally.
15
Stack unwinding cntd. This solution is tedious if the resources are allocated in many different places. A better solution is to wrap the resource in an object, which will be automatically deallocated:
16
Resource Management Example class FilePtr { FILE *p; public: FilePtr(const char *n, const char *a) { p = fopen(n,a); } FilePtr(File *pp) { p = pp; } ~FilePtr() { fclose(p); } operator FILE*() { return p; } };
17
Stack unwinding cntd. FilePtr f(filename, “r”); try {... // here f is used } catch(...) {... } The file is closed by FilePtr ’s destructor, thus it will be closed regardless of the way we exit (normally or with exception).
18
Exceptions in constructor Very convenient If the object is constructed in (dynamic) heap and its constructor throws exception, the memory will be released automatically. The destructor won’t be called.
19
Exceptions in constructor Example: Circle’s constructor throws exception when provided with negative radius: try { c = new Circle(1, 2, -1); } catch(...) { // we should not delete c ! }
20
Standard exceptions exception logic_errorruntime_error ios::failure invalid_argument out_of_range bad_alloc And others.
21
Read yourselves: auto_ptr Similarly to the way we wrapped a FILE pointer, we can wrap any pointer, so that it is automatically deleted when we leave the scope. The auto_ptr which is part of the standard library is a template class for this purpose. MyClass* f(...) { auto_ptr p(new MyClass());... return p.release(); } If an exception occurs prior to return, the instance of MyClass will be automatically deleted by p ’s destructor. u After auto_ptr is copied (to another one) it points nowhere.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.