Your SlideShare is downloading. ×
Exception Handling1
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Exception Handling1

1,046
views

Published on

Published in: Technology, Business

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,046
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
62
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Exception Handlers
    • One exception handler for every type of exception that we want to catch.
    • Exception handlers immediately follow the try block & are denoted by the keyword catch, e.g. try { // code that may generate exceptions } catch(type1 id1) { // handle exceptions of type1 } catch(type2 id2) { // handle exceptions of type2 }
  • 2. Exception Handlers
    • Each catch clause takes a single argument of one particular type.
    • The identifier id1,id2 may be used inside the handler.
    • The identifier is not necessary.
    • Handlers must appear directly after try block with no other code in between .
    • Handler searched like the switch statement except for the break keyword.
  • 3. Exception Specification
    • Informs the user of a function about the type of exceptions the function can throw.
    • Is a part of function declaration appearing after the argument list of the function.
    • Uses keyword throw followed by parenthesized list of all potential exception types.
  • 4. Exception specification contd.
    • void f() throw(toobig, toosmall, divzero);
    • Function can throw exceptions of type toobig, toosmall, divzero only.
    • void f();
    • Any type of exception may be thrown from the function.
    • void f() throw();
    • No exceptions are thrown from a function.
  • 5. unexpected()
    • Called when you throw something other than what appears in the exception specification.
    • Implemented with a pointer to a function.
    • By default, unexpected calls terminate .
    • We can change its behavior using the set_unexpected() function which takes the address of a function with no arguments and void return value.
    • Returns previous value of the unexpected( ) pointer which can be restored later.
    • Header file <exception>
  • 6. set_unexpected() e.g
    • void my_unexpected(){
    • cout << &quot;unexpected exception thrown&quot;;
    • exit(1);
    • }
    • int main() {
    • //set our function handler for unexpected exceptions
    • set_unexpected(my_unexpected);
    • //code that raises an unexpected exception
    • }
  • 7. Uncaught exceptions
    • If none of the exception handlers following a particular try block matches an exception,then
      • Exception moves to the next-higher context, i.e. the function/ try block surrounding the try block that failed to catch the exception.
    • This process continues until, at some level, a handler matches the exception.
    • At that point, the exception is considered “caught” and no further searching occurs.
  • 8. terminate( )
    • terminate() is automatically called if an exception is uncaught.
    • Is actually a pointer to a function.
    • Default value is the Standard C library function abort( ) .
    • No cleanups occur for an uncaught exception
  • 9. set_terminate( )
    • We can install our own terminate() function using the set_terminate() function.
    • Returns a pointer to the previous terminate() function.
    • Custom terminate() takes no arguments and returns a void value.
    • Any terminate( ) handler installed must not return or throw an exception, but instead must call some sort of program-termination function.
  • 10. set_terminate( ) e.g.
    • void terminator() {
    • cout << “Custom terimate ftn&quot; << endl;
    • abort();
    • }
    • void (*old_terminate)()
    • = set_terminate(terminator);
  • 11. set_terminate( ) e.g.
    • #include <eh.h>
    • #include <process.h>
    • #include <iostream.h>
    • void term_func(){
    • cout << &quot;term_func() was called by terminate(). &quot;;
    • // ... cleanup tasks performed here
    • // If this function does not exit, abort is called.
    • exit(-1);
    • }
    • void main(){
    • int i = 10, j = 0, result;
    • set_terminate( term_func );
    • try{
    • if( j == 0 ) throw &quot;Divide by zero!&quot;;
    • else result = i/j;
    • }
    • catch( int ){
    • cout << &quot;Caught some integer exception. &quot;;
    • }
    • cout << &quot;This should never print. &quot;;
    • }
  • 12. Catching any Exception
    • If a function has no exception specification, any type of exception can be thrown.
    • Solution is to create a handler that catches any exception.
    • Done by using ellipses in the argument list.
    • catch(...) {
    • cout << “An exception was thrown&quot; << endl;
    • }
    • Should be put at the end of exception handlers.
  • 13. Rethrowing an exception
    • Sometimes we would want to rethrow the exception that was just caught.
    • Particularly when we use the ellipses to catch any exception because there is no information available about the exception.
    • Accomplished by saying throw with no argument.
    • catch(...) {
    • cout << &quot;an exception was thrown&quot; << endl;
    • throw;
    • }
    • Further catch clauses for the same try block are still ignored
  • 14. Cleaning Up
    • All objects in that scope whose constructors have been completed will have destructors called.
    • If an exception is thrown before a constructor is completed, the associated destructor will not be called for that object.
  • 15. Cleaning Up (e.g)
    • class Cat {
    • public:
    • Cat() { cout << &quot;Cat()&quot; << endl; }
    • ~Cat() { cout << &quot;~Cat()&quot; << endl; }
    • };
    • class Dog {
    • public:
    • void* operator new(size_t sz) {
    • cout << &quot;allocating a Dog&quot; << endl;
    • throw int(47);
    • }
    • void operator delete(void* p) {
    • cout << &quot;deallocating a Dog&quot; << endl;
    • ::delete p;
    • }
    • };
  • 16. Cleaning Up (e.g) contd.
    • class UseResources {
    • Cat* bp;
    • Dog* op;
    • public:
    • UseResources(int count = 1) { cout << &quot;UseResources()&quot; << endl;
    • bp = new Cat[count];
    • op = new Dog; }
    • ~UseResources() { cout << &quot;~UseResources()&quot; << endl;
    • delete []bp; // Array delete
    • delete op; }
    • };
  • 17. Cleaning Up (e.g) contd.
    • int main() {
    • try {
    • UseResources ur(3);
    • } catch(int) {
    • cout << &quot;inside handler&quot; << endl;
    • }
    • }
    • The output is the following
    • UseResources()
    • Cat()
    • Cat()
    • Cat()
    • allocating a Dog
    • inside handler
  • 18. Solution
    • Is to place allocations inside their own objects with their own constructors and destructors.
    • Each allocation becomes atomic.
    • If it fails, the other resource allocation objects are properly cleaned up.
    • Templates offer a solution.
  • 19. Solution using templates
    • template<class T, int sz = 1> class PWrap {
    • T* ptr;
    • public:
    • PWrap() {
    • ptr = new T[sz];
    • cout << &quot;PWrap constructor&quot; << endl; }
    • ~PWrap() {
    • delete []ptr;
    • cout << &quot;PWrap destructor&quot; << endl;
    • }
    • T& operator[](int i){
    • if(i >= 0 && i < sz) return ptr[i]; } };
  • 20. Solution using templates contd.
    • class Cat {
    • public:
    • Cat() { cout << &quot;Cat()&quot; << endl; }
    • ~Cat() { cout << &quot;~Cat()&quot; << endl; }
    • void g() {}
    • };
    • class Dog {
    • public:
    • void* operator new[](size_t sz) {
    • cout << &quot;allocating an Dog&quot; << endl;
    • throw int(47);
    • }
    • void operator delete[](void* p) {
    • cout << &quot;deallocating an Dog&quot; << endl;
    • ::delete p;
    • }
    • };
  • 21. Solution using templates contd.
    • class UseResources {
    • PWrap<Cat, 3> Bonk;
    • PWrap<Dog> Og;
    • public:
    • UseResources() : Bonk(), Og() {
    • cout << &quot;UseResources()&quot; << endl;
    • }
    • ~UseResources() {
    • cout << &quot;~UseResources()&quot; << endl;
    • }
    • void f() { Bonk[1].g(); }
    • };
  • 22. Solution using templates contd.
    • int main() {
    • try {
    • UseResources ur;
    • }
    • catch(int) {
    • cout << &quot;inside handler&quot; << endl;
    • }catch(...) {
    • cout << &quot;inside catch(...)&quot; << endl;
    • }
    • }
  • 23. Solution using templates contd.
    • Cat()
    • Cat()
    • Cat()
    • PWrap constructor
    • allocating a Dog
    • ~Cat()
    • ~Cat()
    • ~Cat()
    • PWrap destructor
    • inside handler
  • 24. Exception Matching
    • Exception-handling system looks through the “nearest” handlers in the order they are written.
    • When it finds a match, the exception is considered handled, and no further searching occurs.
    • Matching an exception doesn’t require a perfect match between the exception and its handler.
    • An object or reference to a derived-class object will match a handler for the base class.
    • If handler is for an object rather than a reference, the exception object is “sliced” as it is passed to the handler.
  • 25. Exception Matching
    • class X {
    • public:
    • class Trouble {};
    • class Small : public Trouble {};
    • class Big : public Trouble {};
    • void f() { throw Big(); }
    • };
  • 26. Exception Matching
    • int main() {
    • X x;
    • try {
    • x.f();
    • }
    • catch(X::Trouble) {
    • cout << &quot;caught Trouble&quot; << endl;
    • }
    • catch(X::Small) { // Hidden by previous handler:
    • cout << &quot;caught Small Trouble&quot; << endl;
    • }
    • catch(X::Big) {
    • cout << &quot;caught Big Trouble&quot; << endl;
    • }
    • }
  • 27. Catch by reference not by value
    • If you throw an object of a derived class and it is caught by value in a handler for an object of the base class, that object is “sliced” – that is, the derived-class elements are cut off and you’ll end up with the base-class object being passed.
    • Chances are this is not what you want because the object will behave like a base-class object and not the derived class object it really is.
  • 28. Catch by reference not by value
    • class Base {
    • public:
    • virtual void what() {
    • cout << &quot;Base&quot; << endl;
    • }
    • };
    • class Derived : public Base {
    • public:
    • void what() {
    • cout << &quot;Derived&quot; << endl;
    • }
    • };
    • void f() { throw Derived(); }
  • 29. Catch by reference not by value
    • int main() {
    • try {
    • f();
    • } catch(Base b) {
    • b.what();
    • }
    • try {
    • f();
    • } catch(Base& b) {
    • b.what();
    • }
    • }
    The output is Base Derived