Download presentation
Presentation is loading. Please wait.
Published byLonnie Newton Modified over 9 years ago
1
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Week 11 Exceptions
2
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel
3
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Errors happen Predictable: –Users type bad data –End of file is reached –File opened is not in the right format Unpredictable –No more memory –File user browsed to is gone now –Hard drive is full
4
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Local Error Handling cout << “Enter a positive number “; cin >> x; while (x < 0) { cout << “Positive please “; cin >> x; }
5
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Delegate to an object cout << “Enter a positive number “; cin >> x; while (!obj.setx(x)) { cout << “Positive please “; cin >> x; } setx() returns false if it didn’t like the number Problem: how do you know what error message to provide?
6
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Delegate to an object cout << “Enter a positive number “; cin >> x; while (!obj.setx(x)) { cout << obj.errormessage(); cin >> x; }
7
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Not all errors can be handled locally Deep inside business logic you should not be contacting the user directly –This may be a GUI app and console output will be ignored –This may be running unattended –Better to report the error to calling code that knows how to reach the user
8
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel How to report errors? Classic approach is to return a signal value: false is good, but an error code may carry more information. –What if you need your return value for an answer? –What if the function doesn’t have a return value (eg constructor, override of a void function) –What if the code that called the function ignores the return value?
9
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel How to report errors? Set a global variable (traditional name is errno) –Still requires calling code to look at it –Multiple errors can tromp on each other You need a way to force the calling code to notice that something has gone wrong You want to pass information along with that notification
10
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Exceptions A non-ignorable notification (with supplementary information) that is thrown by code in trouble It can be caught by any code up the calling chain Catching code tries to recover, but cannot return execution to the trouble spot If your code doesn’t catch it, the operating system will (and it won’t be very pretty.)
11
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Signalling trouble Throw an exception if ( x < 3) throw "x is too small"; If you don’t write code to catch it, it’s an unhandled exception
12
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Unhandled Exceptions
13
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel What can you throw? A literal string such as “x is too small” A number (perhaps an error code) A struct An object –The most useful, since it can combine all these and even have methods that can be called from the catching code
14
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Throws list How do you know what to catch? –You can read the code –There’s an optional addition to the function prototype int foo (int x) throw(char*) Since it’s optional, it has very little effect –foo() can throw anything it likes –Code that calls foo() is not obligated to catch char* or any other kind of exceptions –It’s just for documentation
15
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel What happens when the exception is thrown? If the code is in a try block, the rest of the try block is skipped and control is transferred to the start of the appropriate catch block –Try and catch you will see shortly If the code is not in a try block, the rest of the function is skipped and control leaves the function –If the call to this function was in a try block, control goes to the catch associated with that try –If not, control leaves the function that called this function
16
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel An example void one(char* p) { cout << "entering one" << endl; two(p); cout << "back in one" << endl; } void two(char* p) { cout << "entering two" << endl; if (p) cout << p << endl; else throw "null pointer passed"; cout << "leaving two" << endl; }
17
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel When all goes well one("Hello"); Output: entering one entering two Hello leaving two back in one
18
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel When things go wrong one(NULL); Output: entering one entering two ---- exception is thrown --
19
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Catching the exception You need to set up a try block. This represents the group of statements you are going to try, that you know might throw an exception. Immediately following the try block, place a catch block. It will execute if an exception is thrown. If you catch and process the exception, execution can continue after the catch block and the program will not end abnormally.
20
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Catching the exception The try block does not have to be in the same function as the throw statement – in fact it usually is not. Remember that an exception is a way of signalling trouble back up to the code that called you
21
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Catching the exception void one(char* p) { cout << "entering one" << endl; try { two(p); } catch (char* troublestring) { cout << "two() has a problem: " << troublestring << endl; } cout << "back in one" << endl; }
22
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Output entering one entering two two() has a problem: null pointer passed back in one Notice that execution continued after the catch block.
23
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Catching the exception You can have several catch blocks to catch different types of exceptions (eg int and char*) catch (…) catches any kind of exception at all but you can’t print out what was thrown or otherwise work with it –You can stop your application from blowing up, but not much else
24
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Rethrowing Sometimes you catch an exception so that you can handle it and allow the application to recover Other times you catch an exception just so that you can do some local cleanup In those circumstances, your catch block can rethrow the exception: catch (Ex ex) { cout << "two() has a problem: " << ex << endl; throw; }
25
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Throwing an object class Ex { private: int errorcode; char* troublestring; public: Ex(int ec, char* ts): errorcode(ec), troublestring(ts) {} friend ostream& operator<<(ostream& o, const Ex& e); };
26
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Throwing an Object ostream& operator<<(ostream& o, const Ex& e) { o << "Exception: " << e.errorcode << " (“ << e.troublestring << ")" << endl; return o; }
27
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Throwing an Object void two(char* p) { cout << "entering two" << endl; if (p) cout << p << endl; else { Ex e(15, "null pointer passed"); throw e; } cout << "leaving two" << endl; }
28
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Catching an Object void one(char* p) { cout << "entering one" << endl; try { two(p); } catch (Ex ex) { cout << "two() has a problem: " << ex << endl; } cout << "back in one" << endl; }
29
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel STL Exception class The Standard Template Library defines a class called exception and a number of classes that inherit from it STL functions throw exceptions derived from exception and your code can too: –invalid_argument –out_of_range –overflow_error –etc
30
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Using STL Exceptions #include int stlthrower(int x) { if (x < 4) { invalid_argument e("x too small"); throw e; } return x; }
31
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Catching exceptions by reference try { stlthrower(10); stlthrower(0); } catch (exception& e) { cout << "caught: " << e.what() << endl; }
32
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Unwinding the stack When the exception is thrown, control leaves the function or try block Everything allocated on the stack goes out of scope, and the destructors are called Memory on the heap is not freed but pointers to it may be gone
33
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Unwinding the stack int foo (int x) { int i, j; Employee e; Employee* pe = new Employee(); if ( x < 3) throw "x is too small"; else cout << "x is " << x << endl; return x; }
34
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Unwinding the stack int foo (int x) { int i, j; Employee e; Employee* pe = new Employee(); if ( x < 3) throw "x is too small"; else cout << "x is " << x << endl; delete pe; return x; }
35
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Unwinding the stack int foo (int x) { int i, j; Employee e; Employee* pe = new Employee(); if ( x < 3) { delete pe; throw "x is too small"; } else cout << "x is " << x << endl; delete pe; return x; }
36
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Unwinding the Stack If you have code that deletes memory, ask yourself if it could be skipped when an exception is thrown. Consider moving the delete until after the catch block: void one(char* p) { cout << "entering one" << endl; Employee* pe = new Employee(); try { two(p); } catch (Ex ex) { cout << "two() has a problem: " << ex << endl; } cout << "back in one" << endl; delete pe; }
37
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Cleaning up Memory Putting the delete after the catch block won’t work if you rethrow the exception, because control is leaving the function on the rethrow You could put the delete in the catch block, before the rethrow, and also after it, for those times where there is no exception This is repetitive and error-prone
38
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Duplicate code catch (Ex ex) { cout << "two() has a problem: " << ex << endl; delete pe; throw; } cout << "back in one" << endl; delete pe;
39
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel STL Auto pointer When the stack unwinds, anything you allocated on the stack (int i; Employee e;) is taken care of for you no matter why you left Anything you allocated on the heap you have to take care of yourself What if you allocated something on the stack whose only job was to manage something on the heap?
40
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel STL Auto Pointer This memory manager object would have one variable: a pointer to something on the heap Constructor sets the variable Destructor calls delete using the pointer Operator -> and operator * give access to the object the pointer points to For type-safety, it should be a template
41
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel STL Auto Pointer template class auto_ptr { public: explicit auto_ptr(_Ty *_Ptr = 0) : _Myptr(_Ptr) {} ~auto_ptr() {delete _Myptr;} _Ty& operator*() const {return (*get());} _Ty *operator->() const {return (get());} _Ty *get() const {return (_Myptr);} private: _Ty *_Myptr; };
42
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Using an auto pointer void one(char* p) { cout << "entering one" << endl; auto_ptr pe(new Employee()); try { two(p); pe->display(); cout << *pe << endl; } catch (Ex ex) { cout << "two() has a problem: " << ex << endl; throw; } cout << "back in one" << endl; }
43
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel When to use Exceptions When the error is truly unexpected: out of memory, file has disappeared, etc When the code that can handle it is many function calls away from the code that will detect it When repeatedly checking function returns to pass back error codes will make code harder to read When there is a danger a programmer may forget to check a return code, or the return code is being used
44
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel Exceptions hurt performance Compared to returning a value and checking it you will take a real performance hit by throwing an exception However modern compilers optimize so that trying, in the case where the exception isn’t thrown, actually runs more quickly than an if Reserve exceptions for exceptional circumstances –Never for user input errors!
45
Monday, Mar 24, 2003Kate Gregory with material from Deitel and Deitel For Next class Bring your thoughts and questions, it’s our last lecture We’ll be covering File IO which is not hard at all
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.