Oct 11, 2007 Handling Exceptions in C++ Dr. Partha Pratim Das Interra Systems (India) Pvt. Ltd.   PART B
Agenda <ul><li>PART A </li></ul><ul><ul><li>Exception Fundamentals </li></ul></ul><ul><ul><li>Exceptions in C </li></ul></...
Agenda <ul><li>PART B </li></ul><ul><ul><li>Exception Instrumentations in C++ </li></ul></ul><ul><ul><ul><li>How Compilers...
Agenda <ul><li>PART C </li></ul><ul><ul><li>Designing with Exceptions in C++  </li></ul></ul><ul><ul><ul><li>Analysis & De...
PART B
Exceptions Instrumentations in C++ How compilers manage Exceptional Flow
Exception Handling : Issues <ul><li>Code Isolation </li></ul><ul><ul><li>Separate Exceptions Flow from Normal Flow </li></...
Function Call : Instrumentations <ul><li>Normal Flow </li></ul><ul><ul><li>return  </li></ul></ul><ul><li>Exceptional Flow...
Function Call : Items <ul><li>Normal Call </li></ul><ul><ul><li>Stack Frame </li></ul></ul><ul><ul><li>Context </li></ul><...
Function Call Items : Stack Frame <ul><li>Function parameters  </li></ul><ul><li>Function return address  </li></ul><ul><l...
Function Call Items : Context <ul><li>Register PC / Return Address  </li></ul><ul><ul><li>(eip on x86) </li></ul></ul><ul>...
Function Call Items : Finalization <ul><li>How are the right destructors called in the right order?  </li></ul><ul><ul><li...
Function Call : Normal Flow <ul><li>Caller prepares the Parameters </li></ul><ul><li>Caller calls the Callee </li></ul><ul...
Function Call Items : Stack Frame
Function Call Items : EH Frame
Function Call : Stack Cutting <ul><li>setjmp sets the jmp_buf buffer. </li></ul>#define _JBLEN  16 #define _JBTYPE int // ...
Function Call : Stack Cutting <ul><li>longjmp forces the context (FP, SP and PC) to the jmp_buf buffer stored at setjmp po...
Function Call Items : Stack Frame
Function Call Items : Thunk <ul><li>A delayed computation </li></ul><ul><li>Runtime registers a destructor thunk for the e...
Function Call Items : EH Handler
Function Call : Stack Unwinding <ul><li>Flow: </li></ul><ul><ul><li>Creation of Exception object </li></ul></ul><ul><ul><l...
Function Call : Stack Unwinding <ul><li>Flow: </li></ul><ul><ul><li>Invocation of the right handler. </li></ul></ul><ul><u...
Function Call : Stack Unwinding <ul><li>Data Structures: </li></ul><ul><ul><li>Stack Frame </li></ul></ul><ul><ul><li>RUNT...
Exception Handling : Trade Off
Designing with Exceptions in C++ Glimpses of Design Issues
Designing with Exceptions : Goals <ul><li>“ With Exceptions” !!! </li></ul><ul><ul><li>Designing  in spite of  Exceptions?...
Designing with Exceptions : Goals <ul><li>Graded Goals </li></ul><ul><ul><li>Do Nothing </li></ul></ul><ul><ul><li>No Cras...
Exception Safety : Levels <ul><li>No Exception Safety </li></ul><ul><ul><li>No guarantees are made.  </li></ul></ul><ul><u...
Exception Safety : Levels <ul><li>Strong Exception Guarantee (Commit or Rollback)  </li></ul><ul><ul><li>Failed operations...
Designing with Exceptions : Scope <ul><li>We Consider: </li></ul><ul><ul><li>Function Calls </li></ul></ul><ul><ul><ul><li...
Designing with Exceptions : Scope <ul><li>We do not consider: </li></ul><ul><ul><li>Static Objects </li></ul></ul><ul><ul>...
C++ Ground Rules : Lifetime <ul><li>When does an object's lifetime begin? </li></ul><ul><ul><li>When its constructor compl...
C++ Ground Rules : Lifetime <ul><li>Construction: </li></ul><ul><ul><li>An object is considered  fully constructed  when t...
Anatomy of a Function <ul><li>Safe Operations </li></ul><ul><ul><li>Operations with built-in types </li></ul></ul><ul><ul>...
Exceptional Design Rules Meyers’ Recommendations on Basic Exception Safety
Exception Safety :  Meyers Guidelines <ul><li>Item 9:  Use destructors to prevent resource leaks   </li></ul><ul><li>Item ...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Situation   </li></ul><ul><ul><li>A hierarchy of Polygonal...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Classes </li></ul>class Poly { public:  virtual void plotP...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>plot() for the Graphic Device (unsafe) </li></ul><ul><li>v...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>plot() for the Graphic Device (safe) </li></ul><ul><li>voi...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Litter code with try and catch blocks.  </li></ul><ul><li>...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Smart pointer  </li></ul><ul><ul><li>Is a C++ object  </li...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>auto_ptr </li></ul><ul><li>template<class T>  </li></ul><u...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>plot() for the Graphic Device (safe) </li></ul><ul><li>voi...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Smart Pointers work as Holders of Resources </li></ul><ul>...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Window Handling in Windows OS (unsafe) </li></ul><ul><li>/...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Window Holder </li></ul><ul><li>// class for Holding (acqu...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Window Handling in Windows OS (safe) </li></ul><ul><li>// ...
Meyers [9] :  Use destructors to prevent resource leaks <ul><li>Morale </li></ul><ul><ul><li>Resources should be encapsula...
More Questions   <ul><li>What happens if an exception is thrown in the process of acquiring a resource, that is, in the  c...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Consider:  </li></ul><ul><li>class T { ... };  </li></ul><...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Constructor (unsafe) / Destructor:  </li></ul><ul><li>A::A...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Exception in body: </li></ul><ul><ul><li>operator (T)  may...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Try Exception Fix by Dynamic Allocation </li></ul><ul><ul>...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Constructor (safe) cleans up itself </li></ul><ul><li>A::A...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Constructor (safe): w/o code duplication </li></ul><ul><li...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Reconsider:  </li></ul><ul><li>class T { ... };  </li></ul...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Constructor (unsafe):  </li></ul><ul><li>Exception at Line...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Constructor (safe):  </li></ul><ul><li>T1* A::InitT1(const...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>A better design:  </li></ul><ul><li>class T { ... };  </li...
Meyers [10] :  Prevent resource leaks in constructors   <ul><li>Constructor (safe by design):  </li></ul><ul><li>Exception...
Meyers [10] :  Prevent resource leaks in constructors <ul><li>Moral </li></ul><ul><ul><li>Replace pointer class members wi...
Meyers [11] :  Prevent exceptions from leaving destructors   <ul><li>A destructor is called in two situations  </li></ul><...
Meyers [11] :  Prevent exceptions from leaving destructors   <ul><li>Recap  </li></ul><ul><ul><li>If an exception is throw...
Meyers [11] :  Prevent exceptions from leaving destructors   <ul><li>Consider  </li></ul><ul><li>class Session {  </li></u...
Meyers [11] :  Prevent exceptions from leaving destructors   <ul><li>Manage the exceptions  </li></ul><ul><li>Session::~Se...
Meyers [11] :  Prevent exceptions from leaving destructors   <ul><li>Bite the dust – swallow the exceptions  </li></ul><ul...
Meyers [11] :  Prevent exceptions from leaving destructors   <ul><li>Moral  </li></ul><ul><ul><li>Keep exceptions from pro...
Meyers [12] :  Throwing an exception differs from passing a parameter or calling a virtual function  <ul><li>Control does ...
Meyers [13] :  Catch exceptions by reference
Meyers [14] :    Use exception specifications judiciously
Meyers [15] :    Understand the costs of exception handling
Handling Exceptions in  C & C++ References & Credits
References <ul><li>Handling Exceptions: Part 1 – 4 </li></ul><ul><ul><li>Robert Schmidt </li></ul></ul><ul><li>Modern C++ ...
Credits / Acknowledgements
Thank You
Upcoming SlideShare
Loading in …5
×

Handling Exceptions In C &amp; C++ [Part B] Ver 2

1,451 views

Published on

Second part of my series on Exception Handling. Talks mostly of the stuff in C++. Prepared in 2007

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

  • Be the first to like this

No Downloads
Views
Total views
1,451
On SlideShare
0
From Embeds
0
Number of Embeds
9
Actions
Shares
0
Downloads
69
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • We should outline the various Instrumentations needed for handling Function Calls depending on the kind of exception handling being supported: Normal Flow return Exceptional Flow with Stack Cutting setjmp / longjmp Exceptional Flow with Stack Unwinding try-catch-throw Naturally, keeping with the code separation / code organization motivations in mind, we do not need to refer to any of the local (goto’s) or global (errno / exit() etc) options here. We need to highlight, as we move from #1 to #3, how we are doing in terms of the basic issues (objectives) we have started off with. This will be more a philosophical introduction.
  • These are the items needed for the discussion on Instrumentation. We’ll elaborate them in the following slides. We need to collect information on: How the calling order for finalizers decided? In normal flow and in exceptional flow. What exactly does the EH Handler do to achieve stack unwinding? How a sample EH Frame is laid out.
  • We discuss the stack frame structure here. Function parameters Function return address Frame pointer Local Objects Callee save registers We’ll take a small example and show the stack frame on x86. Good resource is: http://www.unixwiz.net/techtips/win32-callconv-asm.html
  • We discuss the context of a call here. Register PC / Return Address (eip on x86) Register SP / Stack Pointer (esp on x86) Register FP / Frame Pointer or Base Pointer (ebp on x86) With respect to the example, we’ll show the context on x86. Good resources is: http://www.unixwiz.net/techtips/win32-callconv-asm.html
  • We discuss the finalization of a call here. How are the right destructors called in the right order? This is tricky once the function has a multiple return statements before / after a number of local object constructions. We can frame a small example and illustrate.
  • We outline the normal flow in a function call: Caller prepares the Parameters Caller calls the Callee Callee saves the Context (Function Prologue) Callee does the job Callee restores the Context (Function Epilogue) Callee returns Caller cleans up the Parameters Caller uses the return value We can use the stack frame example for illustration. Good resource is: http://www.unixwiz.net/techtips/win32-callconv-asm.html
  • We discuss the enhanced stack frame structure with (bold item). Function parameters Function return address Frame pointer Exception Handler frame Local Objects Callee save registers
  • We need to discuss how EH Frame is maintained. Need more information on this. A good resource is: http://www.osronline.com/custom.cfm?name=articlePrint.cfm&amp;id=469
  • This is the case of handling in C for setjmp / longjmp. Our discussion should follow as: Recap of the setjmp / longjmp with an example. Explanation of the jmp_buf structure for x86-32. This is from the setjmp.h header. With reference to stack frame and context, we need to explain how the information set for the buffer has been chosen. Explanation of the behavior of setjmp – low level steps. Assembly code of setjmp can says that. Explanation of the behavior of longjmp – low level steps. Assembly code of longjmp can says that. Justify why this is ‘stack cutting’ – that is finalizers are not invoked. We use the above example to illustrate. Good resource is: CS360 Lecture notes – Setjmp : http://www.cs.utk.edu/~plank/plank/classes/cs360/360/notes/Setjmp/lecture.html
  • This is the case of handling in C for setjmp / longjmp. Our discussion should follow as: Recap of the setjmp / longjmp with an example. Explanation of the jmp_buf structure for x86-32. This is from the setjmp.h header. With reference to stack frame and context, we need to explain how the information set for the buffer has been chosen. Explanation of the behavior of setjmp – low level steps. Assembly code of setjmp can says that. Explanation of the behavior of longjmp – low level steps. Assembly code of longjmp can says that. Justify why this is ‘stack cutting’ – that is finalizers are not invoked. We use the above example to illustrate. Good resource is: CS360 Lecture notes – Setjmp : http://www.cs.utk.edu/~plank/plank/classes/cs360/360/notes/Setjmp/lecture.html
  • We discuss the additional information that a stack frame structure may need to keep for C++ exceptions. We need to identify them beyond the following. Function parameters Function return address Frame pointer Exception Handler frame Local Objects Callee save registers
  • What is a thunk? The word thunk has two meanings in computer science: a delayed computation (as in functional programming) a mapping of machine data from one system-specific form to another, usually for compatibility reasons. For example, running a 16-bit program on a 32-bit operating system may require a thunk from 16-bit addresses to 32-bit. Thunk in this sense may also refer to mappings from one calling convention to another or from one version of a library to another. This meaning is similar to the first—the &amp;quot;delayed computation&amp;quot; can be thought of as the &amp;quot;update&amp;quot; from the old format to the new. http://en.wikipedia.org/wiki/Thunk Why do we need a destructor thunk for the Exception object? How is it used? Good resource is: Intel presentation on: “C++ Exception Handling for IA-64 Unix”
  • We need to discuss how the EH hook is maintained.
  • This is the case of handling in C++ for try-catch-throw. Our discussion should follow as: Recap of the try-catch-throw with an example. It will be good to use the same example as setjmp / longjmp case. Introduce the basic notions of stack unwinding: Creation of Exception object Placement of destructor thunk for Exception object Wrapping up of the stack frame. Calling of Finalizers Matching for Handler (catch handlers are statically overloaded but dynamically dispatched). Explain why this will need RTTI. Invocation of the right handler. Exit from the handler Invocation of the thunk if no rethrow has been done. Flow / flowchart of the unwind logic. Role of the C++ Runtime system. Outline the data structures required. Stack Frame – modified RUNTIME_FUNCTION UNWIND_INFO TRY_REGION_TABLE CLEANUP_TABLE We use the example to illustrate. Good resources are: Intel presentation on: “C++ Exception Handling for IA-64 Unix” Exceptional Behavior - x64 Structured Exception Handling: http://www.osronline.com/custom.cfm?name=articlePrint.cfm&amp;id=469
  • This is the case of handling in C++ for try-catch-throw. Our discussion should follow as: Recap of the try-catch-throw with an example. It will be good to use the same example as setjmp / longjmp case. Introduce the basic notions of stack unwinding: Creation of Exception object Placement of destructor thunk for Exception object Wrapping up of the stack frame. Calling of Finalizers Matching for Handler (catch handlers are statically overloaded but dynamically dispatched). Explain why this will need RTTI. Invocation of the right handler. Exit from the handler Invocation of the thunk if no rethrow has been done. Flow / flowchart of the unwind logic. Role of the C++ Runtime system. Outline the data structures required. Stack Frame – modified RUNTIME_FUNCTION UNWIND_INFO TRY_REGION_TABLE CLEANUP_TABLE We use the example to illustrate. Good resources are: Intel presentation on: “C++ Exception Handling for IA-64 Unix” Exceptional Behavior - x64 Structured Exception Handling: http://www.osronline.com/custom.cfm?name=articlePrint.cfm&amp;id=469
  • This is the case of handling in C++ for try-catch-throw. Our discussion should follow as: Recap of the try-catch-throw with an example. It will be good to use the same example as setjmp / longjmp case. Introduce the basic notions of stack unwinding: Creation of Exception object Placement of destructor thunk for Exception object Wrapping up of the stack frame. Calling of Finalizers Matching for Handler (catch handlers are statically overloaded but dynamically dispatched). Explain why this will need RTTI. Invocation of the right handler. Exit from the handler Invocation of the thunk if no rethrow has been done. Flow / flowchart of the unwind logic. Role of the C++ Runtime system. Outline the data structures required. Stack Frame – modified RUNTIME_FUNCTION UNWIND_INFO TRY_REGION_TABLE CLEANUP_TABLE We use the example to illustrate. Good resources are: Intel presentation on: “C++ Exception Handling for IA-64 Unix” Exceptional Behavior - x64 Structured Exception Handling: http://www.osronline.com/custom.cfm?name=articlePrint.cfm&amp;id=469
  • Nothing in life comes for free. While Exception support in C++ makes life much easier for the designer, coder and debugger; it makes life tough for the compiler writer. The main two costs are: Overhead during a non-exception flow Loss of Optimization options for the compiler. Good resource is: How much does Exception Handling cost, really? : http://www.nwcpp.org/Downloads/2006/ehc.ppt From this presentation, we can lift a couple of slides (we’ll exclude all references to SEH).
  • Handling Exceptions In C &amp; C++ [Part B] Ver 2

    1. 1. Oct 11, 2007 Handling Exceptions in C++ Dr. Partha Pratim Das Interra Systems (India) Pvt. Ltd. PART B
    2. 2. Agenda <ul><li>PART A </li></ul><ul><ul><li>Exception Fundamentals </li></ul></ul><ul><ul><li>Exceptions in C </li></ul></ul><ul><ul><ul><li>C Language Features </li></ul></ul></ul><ul><ul><ul><li>C Standard Library Support </li></ul></ul></ul><ul><ul><li>SEH in Microsoft C </li></ul></ul><ul><ul><li>Exceptions in C++ </li></ul></ul><ul><ul><ul><li>C++ Language Features </li></ul></ul></ul><ul><ul><ul><ul><li>try–catch–throw </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Exception Specifications </li></ul></ul></ul></ul><ul><ul><ul><li>C++ Standard Library Support </li></ul></ul></ul>
    3. 3. Agenda <ul><li>PART B </li></ul><ul><ul><li>Exception Instrumentations in C++ </li></ul></ul><ul><ul><ul><li>How Compilers Manage Exceptional Flow? </li></ul></ul></ul><ul><ul><li>Designing with Exceptions in C++ </li></ul></ul><ul><ul><ul><li>Goals </li></ul></ul></ul><ul><ul><ul><li>Scope </li></ul></ul></ul><ul><ul><ul><li>Anatomy of a Function </li></ul></ul></ul><ul><ul><ul><li>Meyers Guidelines </li></ul></ul></ul>
    4. 4. Agenda <ul><li>PART C </li></ul><ul><ul><li>Designing with Exceptions in C++ </li></ul></ul><ul><ul><ul><li>Analysis & Design of an Exception-safe stack </li></ul></ul></ul><ul><ul><ul><li>Exception behavior of Standard Library </li></ul></ul></ul><ul><ul><ul><li>Handling Exceptions in Multithreaded Environment </li></ul></ul></ul><ul><ul><ul><li>TR1 Proposal </li></ul></ul></ul>
    5. 5. PART B
    6. 6. Exceptions Instrumentations in C++ How compilers manage Exceptional Flow
    7. 7. Exception Handling : Issues <ul><li>Code Isolation </li></ul><ul><ul><li>Separate Exceptions Flow from Normal Flow </li></ul></ul><ul><ul><li>Separate Error Reporting from Error Handling </li></ul></ul><ul><li>Efficiency </li></ul><ul><ul><li>Minimal Time Overhead for Normal Flow </li></ul></ul><ul><ul><li>Minimal Space Overhead for Normal Flow </li></ul></ul><ul><li>Optimization </li></ul><ul><ul><li>Minimize Loss of code optimizations under Exceptions </li></ul></ul><ul><li>Safety </li></ul><ul><ul><li>Contain the vulnerability of the Program </li></ul></ul>
    8. 8. Function Call : Instrumentations <ul><li>Normal Flow </li></ul><ul><ul><li>return </li></ul></ul><ul><li>Exceptional Flow with Stack Cutting </li></ul><ul><ul><li>setjmp / longjmp </li></ul></ul><ul><li>Exceptional Flow with Stack Unwinding </li></ul><ul><ul><li>try-catch-throw </li></ul></ul>
    9. 9. Function Call : Items <ul><li>Normal Call </li></ul><ul><ul><li>Stack Frame </li></ul></ul><ul><ul><li>Context </li></ul></ul><ul><ul><li>Finalization </li></ul></ul><ul><li>Stack Cutting </li></ul><ul><ul><li>Enhanced Stack Frame </li></ul></ul><ul><ul><li>Exception Handler Frame </li></ul></ul><ul><li>Stack Unwinding </li></ul><ul><ul><li>Destructor Thunk </li></ul></ul><ul><ul><li>EH Handler </li></ul></ul>
    10. 10. Function Call Items : Stack Frame <ul><li>Function parameters </li></ul><ul><li>Function return address </li></ul><ul><li>Frame pointer </li></ul><ul><li>Local Objects </li></ul><ul><li>Callee save registers </li></ul>
    11. 11. Function Call Items : Context <ul><li>Register PC / Return Address </li></ul><ul><ul><li>(eip on x86) </li></ul></ul><ul><li>Register SP / Stack Pointer </li></ul><ul><ul><li>(esp on x86) </li></ul></ul><ul><li>Register FP / Frame Pointer or Base Pointer </li></ul><ul><ul><li>(ebp on x86) </li></ul></ul>
    12. 12. Function Call Items : Finalization <ul><li>How are the right destructors called in the right order? </li></ul><ul><ul><li>On Normal Exit </li></ul></ul><ul><ul><li>On Exceptional Exit </li></ul></ul><ul><li>NOTE: </li></ul><ul><ul><li>This is tricky once the function has a multiple return statements before / after a number of local object constructions </li></ul></ul>
    13. 13. Function Call : Normal Flow <ul><li>Caller prepares the Parameters </li></ul><ul><li>Caller calls the Callee </li></ul><ul><li>Callee saves the Context (Function Prologue) </li></ul><ul><li>Callee does the job </li></ul><ul><li>Callee restores the Context (Function Epilogue) </li></ul><ul><li>Callee returns </li></ul><ul><li>Caller cleans up the Parameters </li></ul><ul><li>Caller uses the return value </li></ul>
    14. 14. Function Call Items : Stack Frame
    15. 15. Function Call Items : EH Frame
    16. 16. Function Call : Stack Cutting <ul><li>setjmp sets the jmp_buf buffer. </li></ul>#define _JBLEN  16 #define _JBTYPE int // Define jump buffer layout for x86 setjmp/longjmp. typedef struct __JUMP_BUFFER {      unsigned long Ebp;     unsigned long Ebx;     unsigned long Edi;     unsigned long Esi;     unsigned long Esp;     unsigned long Eip;     unsigned long Registration;     unsigned long TryLevel;     unsigned long Cookie;     unsigned long UnwindFunc;     unsigned long UnwindData[6]; } _JUMP_BUFFER; typedef _JBTYPE jmp_buf[_JBLEN];
    17. 17. Function Call : Stack Cutting <ul><li>longjmp forces the context (FP, SP and PC) to the jmp_buf buffer stored at setjmp point. </li></ul><ul><li>Effect is – control resurfaces in setjmp and longjmp never returns. </li></ul><ul><li>Stack is ‘CUT’: </li></ul><ul><ul><li>Local objects are not finalized </li></ul></ul><ul><ul><li>All intervening frames are trashed </li></ul></ul>
    18. 18. Function Call Items : Stack Frame
    19. 19. Function Call Items : Thunk <ul><li>A delayed computation </li></ul><ul><li>Runtime registers a destructor thunk for the exception object. </li></ul><ul><li>Catch handler calls the thunk at end. </li></ul>
    20. 20. Function Call Items : EH Handler
    21. 21. Function Call : Stack Unwinding <ul><li>Flow: </li></ul><ul><ul><li>Creation of Exception object </li></ul></ul><ul><ul><li>Placement of destructor thunk for Exception object </li></ul></ul><ul><ul><li>Wrapping up of the stack frame. </li></ul></ul><ul><ul><li>Calling of Finalizers – ‘UNWIND’ </li></ul></ul><ul><ul><li>Matching for Handler </li></ul></ul><ul><ul><ul><li>Catch handlers are statically overloaded but dynamically dispatched. </li></ul></ul></ul><ul><ul><ul><li>Explain why this will need RTTI. </li></ul></ul></ul>
    22. 22. Function Call : Stack Unwinding <ul><li>Flow: </li></ul><ul><ul><li>Invocation of the right handler. </li></ul></ul><ul><ul><li>Exit from the handler </li></ul></ul><ul><ul><li>Invocation of the thunk if no rethrow has been done. </li></ul></ul>
    23. 23. Function Call : Stack Unwinding <ul><li>Data Structures: </li></ul><ul><ul><li>Stack Frame </li></ul></ul><ul><ul><li>RUNTIME_FUNCTION </li></ul></ul><ul><ul><li>UNWIND_INFO </li></ul></ul><ul><ul><li>TRY_REGION_TABLE </li></ul></ul><ul><ul><li>CLEANUP_TABLE </li></ul></ul>
    24. 24. Exception Handling : Trade Off
    25. 25. Designing with Exceptions in C++ Glimpses of Design Issues
    26. 26. Designing with Exceptions : Goals <ul><li>“ With Exceptions” !!! </li></ul><ul><ul><li>Designing in spite of Exceptions? </li></ul></ul><ul><ul><li>Designing with the help of Exceptions? </li></ul></ul><ul><ul><li>Both. </li></ul></ul>
    27. 27. Designing with Exceptions : Goals <ul><li>Graded Goals </li></ul><ul><ul><li>Do Nothing </li></ul></ul><ul><ul><li>No Crash </li></ul></ul><ul><ul><li>No Resource Leak </li></ul></ul><ul><ul><li>Valid System State </li></ul></ul><ul><ul><li>Unchanged System State </li></ul></ul><ul><ul><li>Works ALWAYS </li></ul></ul>No Safety Minimal Safety Basic Safety Strong Safety No-Throw Safety
    28. 28. Exception Safety : Levels <ul><li>No Exception Safety </li></ul><ul><ul><li>No guarantees are made. </li></ul></ul><ul><ul><li>This is never acceptable in a production environment. </li></ul></ul><ul><li>Minimal Exception Safety </li></ul><ul><ul><li>Partial execution of failed operations may store invalid data but will not cause a crash. </li></ul></ul><ul><ul><li>This may be acceptable for a graceful exit. </li></ul></ul><ul><li>Basic Exception Guarantee </li></ul><ul><ul><li>Partial execution of failed operations can cause side effects </li></ul></ul><ul><ul><li>Invariants on the state are preserved </li></ul></ul><ul><ul><li>Any stored data will contain valid values. </li></ul></ul>
    29. 29. Exception Safety : Levels <ul><li>Strong Exception Guarantee (Commit or Rollback) </li></ul><ul><ul><li>Failed operations are guaranteed to have no side effects. </li></ul></ul><ul><ul><li>Operations either succeed or have no effect at all. </li></ul></ul><ul><li>No-Throw Guarantee (Failure Transparency) </li></ul><ul><ul><li>Operations are guaranteed to succeed and satisfy all requirements even in presence of exceptional situations. </li></ul></ul><ul><ul><li>Ideal; but may be unrealistic. </li></ul></ul><ul><ul><li>Usually not possible in libraries where complete knowledge of the application is not available. </li></ul></ul>
    30. 30. Designing with Exceptions : Scope <ul><li>We Consider: </li></ul><ul><ul><li>Function Calls </li></ul></ul><ul><ul><ul><li>Global Functions </li></ul></ul></ul><ul><ul><ul><li>Static Methods </li></ul></ul></ul><ul><ul><ul><li>Non-Static Methods </li></ul></ul></ul><ul><ul><ul><li>Virtual Functions </li></ul></ul></ul><ul><ul><ul><li>Operators (Overloaded) </li></ul></ul></ul><ul><ul><li>Objects </li></ul></ul><ul><ul><ul><li>Automatic </li></ul></ul></ul><ul><ul><ul><li>Dynamic </li></ul></ul></ul>
    31. 31. Designing with Exceptions : Scope <ul><li>We do not consider: </li></ul><ul><ul><li>Static Objects </li></ul></ul><ul><ul><li>Asynchronous Exceptions </li></ul></ul><ul><ul><li>Standard Library Objects </li></ul></ul><ul><ul><li>STL Containers </li></ul></ul><ul><ul><li>… </li></ul></ul>
    32. 32. C++ Ground Rules : Lifetime <ul><li>When does an object's lifetime begin? </li></ul><ul><ul><li>When its constructor completes successfully and returns normally. </li></ul></ul><ul><li>When does an object's lifetime end? </li></ul><ul><ul><li>When its destructor begins. </li></ul></ul><ul><li>What is the state of the object after its lifetime has ended? </li></ul><ul><ul><li>There is no object. </li></ul></ul>
    33. 33. C++ Ground Rules : Lifetime <ul><li>Construction: </li></ul><ul><ul><li>An object is considered fully constructed when the control goes out of constructor. </li></ul></ul><ul><li>Destruction: </li></ul><ul><ul><li>C++ refuses to call destructors for objects that haven't been fully constructed </li></ul></ul><ul><ul><li>When an object is destructed, all fully constructed sub-objects are destructed. </li></ul></ul><ul><li>Finalization: </li></ul><ul><ul><li>Destructors for all local objects are called on exit (except for abort(), exit() and longjmp()). </li></ul></ul>
    34. 34. Anatomy of a Function <ul><li>Safe Operations </li></ul><ul><ul><li>Operations with built-in types </li></ul></ul><ul><ul><li>Compiler Mechanisms </li></ul></ul><ul><ul><ul><li>Call, Return, Try, Throw, Catch </li></ul></ul></ul><ul><ul><li>Safe Functions </li></ul></ul><ul><li>Unsafe Operations </li></ul><ul><ul><li>Functions </li></ul></ul><ul><ul><li>Construction </li></ul></ul><ul><ul><li>Copy Construction </li></ul></ul><ul><ul><li>Copy Assignment </li></ul></ul><ul><ul><li>Destruction </li></ul></ul><ul><ul><li>operator new / delete </li></ul></ul><ul><ul><li>… </li></ul></ul><ul><li>class A { }; </li></ul><ul><li>A Viscera( </li></ul><ul><ul><li>A x , // Argument Copy </li></ul></ul><ul><ul><li>A& rx , </li></ul></ul><ul><ul><li>A* px ) </li></ul></ul><ul><li>{ // Local objects </li></ul><ul><ul><li>A a ; </li></ul></ul><ul><ul><li>A& ra = *px ; </li></ul></ul><ul><ul><li>A* pa = new A(rx) ; </li></ul></ul><ul><ul><li>try { // ... </li></ul></ul><ul><ul><ul><li>// Parameter Copy </li></ul></ul></ul><ul><ul><ul><li>A a = // Return Value Copy </li></ul></ul></ul><ul><ul><ul><li>Viscera( a , *pa , &ra ); </li></ul></ul></ul><ul><ul><ul><li>// ... </li></ul></ul></ul><ul><ul><li>} catch ( A& e ) { </li></ul></ul><ul><ul><ul><li>// Handler </li></ul></ul></ul><ul><ul><li>} // Exception Destructor Thunk </li></ul></ul><ul><ul><li>// Exception Object Copy </li></ul></ul><ul><ul><li>throw x ; // Exception Exit </li></ul></ul><ul><ul><li>// Temporary Object Copy </li></ul></ul><ul><ul><li>return a ; // Normal Exit </li></ul></ul><ul><li>} // Local Object Cleanup </li></ul>
    35. 35. Exceptional Design Rules Meyers’ Recommendations on Basic Exception Safety
    36. 36. Exception Safety : Meyers Guidelines <ul><li>Item 9:  Use destructors to prevent resource leaks   </li></ul><ul><li>Item 10:  Prevent resource leaks in constructors   </li></ul><ul><li>Item 11:  Prevent exceptions from leaving destructors   </li></ul><ul><li>Item 12:  Understand how throwing an exception differs from passing a parameter or calling a virtual function   </li></ul><ul><li>Item 13:  Catch exceptions by reference   </li></ul><ul><li>Item 14:  Use exception specifications judiciously   </li></ul><ul><li>Item 15:  Understand the costs of exception handling   </li></ul>
    37. 37. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Situation </li></ul><ul><ul><li>A hierarchy of Polygonal objects </li></ul></ul><ul><ul><li>Two methods: </li></ul></ul><ul><ul><ul><li>Poly* readPoly(istream&) </li></ul></ul></ul><ul><ul><ul><ul><li>Read from input stream, and </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Create (through factory). </li></ul></ul></ul></ul><ul><ul><ul><li>virtual void plotPoly() </li></ul></ul></ul><ul><ul><ul><ul><li>Object drawn on the plotter device </li></ul></ul></ul></ul>Poly Quad Tri
    38. 38. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Classes </li></ul>class Poly { public: virtual void plotPoly() = 0; ... }; class Quad: public Poly { public: virtual void plotPoly(); ... }; class Tri: public Poly { public: virtual void plotPoly(); ... };
    39. 39. Meyers [9] : Use destructors to prevent resource leaks <ul><li>plot() for the Graphic Device (unsafe) </li></ul><ul><li>void plot(istream& myStream) { </li></ul><ul><ul><li>// while there's data </li></ul></ul><ul><ul><li>while (myStream) { </li></ul></ul><ul><ul><ul><li>// get next poly </li></ul></ul></ul><ul><ul><ul><li>Poly *pPoly = readPoly(myStream); </li></ul></ul></ul><ul><ul><ul><li>// Plot the polygon </li></ul></ul></ul><ul><ul><ul><li>pPoly->plotPoly(); </li></ul></ul></ul><ul><ul><ul><li>// delete object that </li></ul></ul></ul><ul><ul><ul><li>// readPoly returned </li></ul></ul></ul><ul><ul><ul><li>delete pPoly; </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>plotPoly() throws  *pPoly leaks
    40. 40. Meyers [9] : Use destructors to prevent resource leaks <ul><li>plot() for the Graphic Device (safe) </li></ul><ul><li>void plot(istream& myStream) { </li></ul><ul><li> // while there's data </li></ul><ul><li>while (myStream) { </li></ul><ul><ul><ul><li>// get next poly </li></ul></ul></ul><ul><ul><ul><li>Poly *pPoly = readPoly(myStream); </li></ul></ul></ul><ul><ul><ul><li>try { </li></ul></ul></ul><ul><ul><ul><ul><ul><li>// Plot the polygon </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>pPoly->plotPoly(); </li></ul></ul></ul></ul></ul><ul><ul><ul><li>} catch (...) </li></ul></ul></ul><ul><ul><ul><li>{ </li></ul></ul></ul><ul><ul><ul><li>// delete object - exception </li></ul></ul></ul><ul><ul><ul><li>delete pPoly; </li></ul></ul></ul><ul><ul><ul><li>throw; // passes on exception </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>// delete object – no exception </li></ul></ul></ul><ul><ul><ul><li>delete pPoly; </li></ul></ul></ul><ul><li>} </li></ul><ul><li>} </li></ul>Code Duplication
    41. 41. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Litter code with try and catch blocks. </li></ul><ul><li>Duplicate cleanup code </li></ul><ul><ul><li>Normal paths and </li></ul></ul><ul><ul><li>Exceptional paths. </li></ul></ul><ul><ul><li>Executes anyway! </li></ul></ul><ul><li>Move the cleanup code that must always be executed into the destructor for an object local to plot(). </li></ul><ul><ul><li>Local objects are always destroyed when leaving a function, regardless of how that function is exited. </li></ul></ul><ul><li>The solution is to replace the pointer with an object that acts like a pointer </li></ul><ul><ul><li>aka, Smart Pointer </li></ul></ul>
    42. 42. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Smart pointer </li></ul><ul><ul><li>Is a C++ object </li></ul></ul><ul><ul><li>Stores pointers to dynamically allocated (heap / free store) objects </li></ul></ul><ul><ul><li>Improves raw pointers by implementing </li></ul></ul><ul><ul><ul><li>Construction & Destruction </li></ul></ul></ul><ul><ul><ul><li>Copying & Assignment </li></ul></ul></ul><ul><ul><ul><li>Dereferencing: </li></ul></ul></ul><ul><ul><ul><ul><li>operator–> </li></ul></ul></ul></ul><ul><ul><ul><ul><li>operator* </li></ul></ul></ul></ul><ul><ul><li>Grossly mimics raw pointer syntax & semantics </li></ul></ul>
    43. 43. Meyers [9] : Use destructors to prevent resource leaks <ul><li>auto_ptr </li></ul><ul><li>template<class T> </li></ul><ul><li>class auto_ptr { </li></ul><ul><li>public: </li></ul><ul><ul><li>// save ptr to object </li></ul></ul><ul><ul><li>auto_ptr(T *p = 0): ptr_(p) {} </li></ul></ul><ul><ul><li>// delete ptr to object </li></ul></ul><ul><ul><li>~auto_ptr() { delete ptr_; } </li></ul></ul><ul><ul><li>// Indirection </li></ul></ul><ul><ul><li>T* operator->() const { return ptr_; } </li></ul></ul><ul><ul><li>... </li></ul></ul><ul><li>private: </li></ul><ul><ul><li>// raw ptr to object </li></ul></ul><ul><ul><li>T *ptr_; </li></ul></ul><ul><li>}; </li></ul>
    44. 44. Meyers [9] : Use destructors to prevent resource leaks <ul><li>plot() for the Graphic Device (safe) </li></ul><ul><li>void plot(istream& myStream) { </li></ul><ul><ul><li>// while there's data </li></ul></ul><ul><ul><li>while (myStream) { </li></ul></ul><ul><ul><ul><li>// get next poly </li></ul></ul></ul><ul><ul><ul><li>auto_ptr<Poly> pPoly(readPoly(myStream)); </li></ul></ul></ul><ul><ul><ul><li>// Plot the polygon </li></ul></ul></ul><ul><ul><ul><li>pPoly->plotPoly(); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>pPoly->plotPoly(); means (pPoly.operator->())->plotPoly();
    45. 45. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Smart Pointers work as Holders of Resources </li></ul><ul><ul><li>RAII – Resource Acquisition is Initialization Idiom </li></ul></ul><ul><ul><li>Scoped Acquisition – Release Paradigm </li></ul></ul><ul><ul><ul><li>Acquires / Locks in Constructor </li></ul></ul></ul><ul><ul><ul><li>Releases / Unlocks in Destructor </li></ul></ul></ul><ul><ul><ul><li>Ensures safety on face of exceptions </li></ul></ul></ul>
    46. 46. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Window Handling in Windows OS (unsafe) </li></ul><ul><li>// This function leaks resources </li></ul><ul><li>// if an exception is thrown </li></ul><ul><li>void Display(const Information& info) { </li></ul><ul><ul><li>HANDLE w = CreateWindow( /* Creation Parameters */ ); </li></ul></ul><ul><ul><li>/* Data preparations */ </li></ul></ul><ul><ul><li>RenderWindow(w, info, /* Display Parameters */); </li></ul></ul><ul><ul><li>/* Data Cleanup */ </li></ul></ul><ul><ul><li>DestroyWindow(w); </li></ul></ul><ul><li>} </li></ul>
    47. 47. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Window Holder </li></ul><ul><li>// class for Holding (acquiring and </li></ul><ul><li>// releasing) a window handle </li></ul><ul><li>class WindowHolder { </li></ul><ul><li>public: </li></ul><ul><ul><li>WindowHolder(HANDLE h): w_(h) {} </li></ul></ul><ul><ul><li>~WindowHolder() { DestroyWindow(w_); } </li></ul></ul><ul><ul><li>operator HANDLE() { return w_; } </li></ul></ul><ul><li>private: </li></ul><ul><li>HANDLE w_; </li></ul><ul><ul><li>// Stop free functions being available </li></ul></ul><ul><ul><li>WindowHolder(const WindowHolder&); </li></ul></ul><ul><ul><li>WindowHolder& operator=(const WindowHolder&); </li></ul></ul><ul><li>}; </li></ul>
    48. 48. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Window Handling in Windows OS (safe) </li></ul><ul><li>// This function cleans up resources - always </li></ul><ul><li>void Display(const Information& info) { </li></ul><ul><ul><li>WindowHolder </li></ul></ul><ul><ul><ul><li>w(CreateWindow( /* Creation Parameters */ )); </li></ul></ul></ul><ul><ul><li>/* Data preparations */ </li></ul></ul><ul><ul><li>// WindowHandle is implicitly converted to HANDLE </li></ul></ul><ul><ul><li>RenderWindow(w, info, /* Display Parameters */); </li></ul></ul><ul><ul><li>/* Data Cleanup */ </li></ul></ul><ul><li>} </li></ul>
    49. 49. Meyers [9] : Use destructors to prevent resource leaks <ul><li>Morale </li></ul><ul><ul><li>Resources should be encapsulated inside objects. </li></ul></ul><ul><ul><li>Usually avoids resource leaks in the face of exceptions. </li></ul></ul>
    50. 50. More Questions <ul><li>What happens if an exception is thrown in the process of acquiring a resource, that is, in the constructor of a resource-acquiring class? </li></ul><ul><li>What happens if an exception is thrown during the automatic destruction of such resources? </li></ul>
    51. 51. Meyers [10] : Prevent resource leaks in constructors <ul><li>Consider:  </li></ul><ul><li>class T { ... }; </li></ul><ul><li>class T1 { public: T1(const T&); ... }; </li></ul><ul><li>class T2 { public: T2(const T&); ... }; </li></ul><ul><li>class A { </li></ul><ul><li>public: </li></ul><ul><ul><li>A(const T&, const T& = (T)0, const T& = (T)0); </li></ul></ul><ul><ul><li>~A(); </li></ul></ul><ul><ul><li>void f(const T&); ... </li></ul></ul><ul><li>private: </li></ul><ul><ul><li>T m_; </li></ul></ul><ul><ul><li>T1 *p1_; </li></ul></ul><ul><ul><li>T2 *p2_; </li></ul></ul><ul><li>}; </li></ul>
    52. 52. Meyers [10] : Prevent resource leaks in constructors <ul><li>Constructor (unsafe) / Destructor:  </li></ul><ul><li>A::A(const T& d, const T& s1, const T& s2): </li></ul><ul><ul><li>m_(d), p1_(0), p2_(0) </li></ul></ul><ul><li>{ </li></ul><ul><ul><li>if (s1 != (T)0) </li></ul></ul><ul><ul><ul><li>p1_ = new T1(s1); // 1 </li></ul></ul></ul><ul><ul><li>if (s2 != (T)0) </li></ul></ul><ul><ul><ul><li>p2_ = new T2(s2); // 2 </li></ul></ul></ul><ul><li>} </li></ul><ul><li>A::~A() </li></ul><ul><li>{ </li></ul><ul><ul><li>delete p1_; </li></ul></ul><ul><ul><li>delete p2_’ </li></ul></ul><ul><li>} </li></ul>
    53. 53. Meyers [10] : Prevent resource leaks in constructors <ul><li>Exception in body: </li></ul><ul><ul><li>operator (T) may throw. </li></ul></ul><ul><ul><li>T::operator != may throw </li></ul></ul><ul><ul><li>T::operator new may throw bad_alloc </li></ul></ul><ul><ul><li>Constructor for T1 or T2 may throw </li></ul></ul><ul><li>Exception at Line 1 is safe.  </li></ul><ul><ul><li>m_ gets destructed. </li></ul></ul><ul><li>Exception at Line 2 leaks p1_ .  </li></ul><ul><ul><li>A::~A() does not get called as the object is not there. </li></ul></ul><ul><li>A::A(const T& d, const T& s1, const T& s2):m_(d), p1_(0), p2_(0) { </li></ul><ul><ul><li>if (s1 != (T)0) p1_ = new T1(s1); // Line 1 </li></ul></ul><ul><ul><li>if (s2 != (T)0) p2_ = new T2(s2); // Line 2 } </li></ul></ul>
    54. 54. Meyers [10] : Prevent resource leaks in constructors <ul><li>Try Exception Fix by Dynamic Allocation </li></ul><ul><ul><li>Doesn’t work as pA is never assigned if the following throws </li></ul></ul><ul><ul><ul><li>T::operator new </li></ul></ul></ul><ul><ul><ul><li>Constructor for A </li></ul></ul></ul><ul><li>{ </li></ul><ul><ul><li>A *pA = 0; </li></ul></ul><ul><ul><li>try { </li></ul></ul><ul><ul><ul><li>pA = new A(d, s1, s2); </li></ul></ul></ul><ul><ul><ul><li>... </li></ul></ul></ul><ul><ul><li>} catch (...) { // catch all exceptions </li></ul></ul><ul><ul><ul><li>delete pA; // delete pA on an exception </li></ul></ul></ul><ul><ul><ul><li>throw; // Rethrow exception </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>delete pA; // delete pA normally </li></ul></ul><ul><li>} </li></ul>
    55. 55. Meyers [10] : Prevent resource leaks in constructors <ul><li>Constructor (safe) cleans up itself </li></ul><ul><li>A::A(const T& d, const T& s1, const T& s2): </li></ul><ul><ul><li>m_(d), p1_(0), p2_(0) </li></ul></ul><ul><li>{ </li></ul><ul><ul><li>try { </li></ul></ul><ul><ul><ul><li>if (s1 != (T)0) </li></ul></ul></ul><ul><ul><ul><ul><li>p1_ = new T1(s1); // 1 </li></ul></ul></ul></ul><ul><ul><ul><li>if (s2 != (T)0) </li></ul></ul></ul><ul><ul><ul><ul><li>p2_ = new T2(s2); // 2 </li></ul></ul></ul></ul><ul><ul><li>} catch (...) { </li></ul></ul><ul><ul><ul><li>delete p1_; </li></ul></ul></ul><ul><ul><ul><li>delete p2_; </li></ul></ul></ul><ul><ul><ul><li>throw; </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul><ul><li>A::~A() </li></ul><ul><li>{ </li></ul><ul><ul><li>delete p1_; </li></ul></ul><ul><ul><li>delete p2_’ </li></ul></ul><ul><li>} </li></ul>
    56. 56. Meyers [10] : Prevent resource leaks in constructors <ul><li>Constructor (safe): w/o code duplication </li></ul><ul><li>A::A(const T& d, const T& s1, const T& s2): </li></ul><ul><ul><li>m_(d), p1_(0), p2_(0) </li></ul></ul><ul><li>{ </li></ul><ul><ul><li>try { </li></ul></ul><ul><ul><ul><li>if (s1 != (T)0) </li></ul></ul></ul><ul><ul><ul><ul><li>p1_ = new T1(s1); // 1 </li></ul></ul></ul></ul><ul><ul><ul><li>if (s2 != (T)0) </li></ul></ul></ul><ul><ul><ul><ul><li>p2_ = new T2(s2); // 2 </li></ul></ul></ul></ul><ul><ul><li>} catch (...) { </li></ul></ul><ul><ul><ul><li>CleanUp(); </li></ul></ul></ul><ul><ul><ul><li>throw; </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul><ul><li>A::~A() </li></ul><ul><li>{ </li></ul><ul><ul><li>CleanUp(); </li></ul></ul><ul><li>} </li></ul><ul><li>A::CleanUp() </li></ul><ul><li>{ </li></ul><ul><ul><li>delete p1_; </li></ul></ul><ul><ul><li>delete p2_; </li></ul></ul><ul><li>} </li></ul>
    57. 57. Meyers [10] : Prevent resource leaks in constructors <ul><li>Reconsider:  </li></ul><ul><li>class T { ... }; </li></ul><ul><li>class T1 { public: T1(const T&); ... }; </li></ul><ul><li>class T2 { public: T2(const T&); ... }; </li></ul><ul><li>class A { </li></ul><ul><li>public: </li></ul><ul><ul><li>A(const T&, const T& = (T)0, const T& = (T)0); </li></ul></ul><ul><ul><li>~A(); </li></ul></ul><ul><ul><li>void f(const T&); ... </li></ul></ul><ul><li>private: </li></ul><ul><ul><li>T m_; </li></ul></ul><ul><ul><li>T1 * const p1_; </li></ul></ul><ul><ul><li>T2 * const p2_; </li></ul></ul><ul><li>}; </li></ul>
    58. 58. Meyers [10] : Prevent resource leaks in constructors <ul><li>Constructor (unsafe):  </li></ul><ul><li>Exception at Line 1 is safe.  </li></ul><ul><ul><li>m_ gets destructed. </li></ul></ul><ul><li>Exception at Line 2 leaks p1_ .  </li></ul><ul><ul><li>A::~A() does not get called. </li></ul></ul><ul><li>No try-catch on Initializer list – only expressions. </li></ul><ul><li>A::A(const T& d, const T& s1, const T& s2): </li></ul><ul><ul><li>m_(d), </li></ul></ul><ul><ul><li>p1_((s1 != (T)0)? new T1(s1): 0), // Line 1 </li></ul></ul><ul><ul><li>p2_((s2 != (T)0)? new T2(s2): 0) // Line 2 </li></ul></ul><ul><li>{ } </li></ul>
    59. 59. Meyers [10] : Prevent resource leaks in constructors <ul><li>Constructor (safe):  </li></ul><ul><li>T1* A::InitT1(const T&s) { </li></ul><ul><ul><li>if (s != (T)0) return new T1(s); </li></ul></ul><ul><ul><li>else return (T1*)0; } </li></ul></ul><ul><li>T2* A::InitT2(const T&s) { </li></ul><ul><ul><li>try { </li></ul></ul><ul><ul><ul><li>if (s != (T)0) return new T2(s); </li></ul></ul></ul><ul><ul><ul><li>else return (T2*)0; </li></ul></ul></ul><ul><ul><li>} catch (...) { </li></ul></ul><ul><ul><ul><li>delete p1_; </li></ul></ul></ul><ul><ul><ul><li>throw; } </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>A::A(const T& d, const T& s1, const T& s2): </li></ul><ul><ul><li>m_(d), p1_(InitT1(s1)), p2_(InitT2(s2)) { } </li></ul></ul>
    60. 60. Meyers [10] : Prevent resource leaks in constructors <ul><li>A better design:  </li></ul><ul><li>class T { ... }; </li></ul><ul><li>class T1 { public: T1(const T&); ... }; </li></ul><ul><li>class T2 { public: T2(const T&); ... }; </li></ul><ul><li>class A { </li></ul><ul><li>public: </li></ul><ul><ul><li>A(const T&, const T& = (T)0, const T& = (T)0); </li></ul></ul><ul><ul><li>~A(); </li></ul></ul><ul><ul><li>void f(const T&); ... </li></ul></ul><ul><li>private: </li></ul><ul><ul><li>T m_; </li></ul></ul><ul><ul><li>const auto_ptr<T1> p1_; </li></ul></ul><ul><ul><li>const auto_ptr<T2> p2_; </li></ul></ul><ul><li>}; </li></ul>
    61. 61. Meyers [10] : Prevent resource leaks in constructors <ul><li>Constructor (safe by design):  </li></ul><ul><li>Exception at Line 1 is safe.  </li></ul><ul><ul><li>m_ gets destructed. </li></ul></ul><ul><li>Exception at Line 2 is safe.  </li></ul><ul><ul><li>m_ & p1_ get destructed. </li></ul></ul><ul><li>// Constructor </li></ul><ul><li>A::A(const T& d, const T& s1, const T& s2): </li></ul><ul><ul><li>m_(d), </li></ul></ul><ul><ul><li>p1_((s1 != (T)0)? new T1(s1): 0), // Line 1 </li></ul></ul><ul><ul><li>p2_((s2 != (T)0)? new T2(s2): 0) // Line 2 </li></ul></ul><ul><li>{ } </li></ul>// Destructor A::~A() { }
    62. 62. Meyers [10] : Prevent resource leaks in constructors <ul><li>Moral </li></ul><ul><ul><li>Replace pointer class members with their corresponding auto_ptr objects </li></ul></ul><ul><ul><ul><li>Fortifies constructors against resource leaks in the presence of exceptions, </li></ul></ul></ul><ul><ul><ul><li>Eliminates the need to manually deallocate resources in destructors, and </li></ul></ul></ul><ul><ul><ul><li>Allows const member pointers to be handled in the same graceful fashion as non-const pointers. </li></ul></ul></ul>
    63. 63. Meyers [11] : Prevent exceptions from leaving destructors <ul><li>A destructor is called in two situations </li></ul><ul><ul><li>When an object is destroyed under “normal” conditions </li></ul></ul><ul><ul><ul><li>When it goes out of scope or </li></ul></ul></ul><ul><ul><ul><li>Is explicitly deleted. </li></ul></ul></ul><ul><ul><li>When an object is destroyed by the exception-handling mechanism during the stack-unwinding part of “exception propagation”. </li></ul></ul>
    64. 64. Meyers [11] : Prevent exceptions from leaving destructors <ul><li>Recap </li></ul><ul><ul><li>If an exception is thrown when another exception is active, terminate() is called and the program immediately terminates. </li></ul></ul><ul><ul><li>From within a destructor, there is no robust way to determine if an exception is active. </li></ul></ul>
    65. 65. Meyers [11] : Prevent exceptions from leaving destructors <ul><li>Consider </li></ul><ul><li>class Session { </li></ul><ul><ul><li>public: </li></ul></ul><ul><ul><ul><li>Session(); </li></ul></ul></ul><ul><ul><ul><li>~Session(); </li></ul></ul></ul><ul><ul><ul><li>... </li></ul></ul></ul><ul><ul><li>private: </li></ul></ul><ul><ul><ul><li>static void logCreation(Session *); </li></ul></ul></ul><ul><ul><ul><li>static void logDestruction(Session *); </li></ul></ul></ul><ul><li>}; </li></ul><ul><li>Session::~Session() { </li></ul><ul><ul><li>// Fatal to throw here </li></ul></ul><ul><ul><li>logDestruction(this); </li></ul></ul><ul><li>}; </li></ul>
    66. 66. Meyers [11] : Prevent exceptions from leaving destructors <ul><li>Manage the exceptions </li></ul><ul><li>Session::~Session() { </li></ul><ul><ul><li>try { </li></ul></ul><ul><ul><ul><li>logDestruction(this); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>catch (...) { </li></ul></ul><ul><ul><ul><li>// Fatal again if operator<<() throws </li></ul></ul></ul><ul><ul><ul><li>cerr << &quot;Unable to log destruction of Session object&quot; </li></ul></ul></ul><ul><ul><ul><ul><li><< &quot;at address &quot; </li></ul></ul></ul></ul><ul><ul><ul><ul><li><< this </li></ul></ul></ul></ul><ul><ul><ul><ul><li><< &quot;. &quot;; </li></ul></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>}; </li></ul>
    67. 67. Meyers [11] : Prevent exceptions from leaving destructors <ul><li>Bite the dust – swallow the exceptions </li></ul><ul><li>Session::~Session() { </li></ul><ul><ul><li>try { </li></ul></ul><ul><ul><ul><li>logDestruction(this); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>catch (...) { } </li></ul></ul><ul><li>}; </li></ul>
    68. 68. Meyers [11] : Prevent exceptions from leaving destructors <ul><li>Moral </li></ul><ul><ul><li>Keep exceptions from propagating out of destructors. </li></ul></ul><ul><ul><ul><li>Prevents terminate from being called during the stack-unwinding part of exception propagation. </li></ul></ul></ul><ul><ul><ul><li>Helps ensure that destructors always accomplish everything they are supposed to accomplish. </li></ul></ul></ul>
    69. 69. Meyers [12] : Throwing an exception differs from passing a parameter or calling a virtual function <ul><li>Control does not return to the throw site. </li></ul><ul><li>Throw always copies the object. </li></ul><ul><li>Catch needs to clean-up the thrown object. </li></ul><ul><li>Parameter Matching is exact for Catch and done with the static type </li></ul><ul><li>Overloaded Catch clauses are tried in lexical order. </li></ul>
    70. 70. Meyers [13] : Catch exceptions by reference
    71. 71. Meyers [14] : Use exception specifications judiciously
    72. 72. Meyers [15] : Understand the costs of exception handling
    73. 73. Handling Exceptions in C & C++ References & Credits
    74. 74. References <ul><li>Handling Exceptions: Part 1 – 4 </li></ul><ul><ul><li>Robert Schmidt </li></ul></ul><ul><li>Modern C++ Design: Generic Programming & Design Pattern Applied </li></ul><ul><ul><li>Andrei Alexandrescu </li></ul></ul><ul><li>Exceptional C++ & More Exceptional C++ </li></ul><ul><ul><li>Herb Sutter </li></ul></ul><ul><li>Effective C++ & More Effective C++ </li></ul><ul><ul><li>Scott Meyers </li></ul></ul><ul><li>Standard Features Missing From VC++ 7.1. Part I: Exception Specifications </li></ul><ul><ul><li>Nemanja Trifunovic http://www.codeproject.com/cpp/stdexceptionspec.asp </li></ul></ul><ul><li>A Pragmatic Look at Exception Specifications </li></ul><ul><ul><li>http://www.gotw.ca/publications/mill22.htm </li></ul></ul>
    75. 75. Credits / Acknowledgements
    76. 76. Thank You

    ×