Presentation is loading. Please wait.

Presentation is loading. Please wait.

The Beauty of Destruction Pete Isensee Microsoft Game Developers Conference March 2009.

Similar presentations


Presentation on theme: "The Beauty of Destruction Pete Isensee Microsoft Game Developers Conference March 2009."— Presentation transcript:

1 The Beauty of Destruction Pete Isensee Microsoft Game Developers Conference March 2009

2 C++ Destructor Definition One Special Deterministic Automatic Symmetric Member Function With A special name No parameters No return type Designed to Give last rites Before object death

3 Language Comparison LanguageNameNotationDeterministicNotes Cn/a C++Destructor~T()Yes C++/CLIDestructor~T()Yes C++/CLIFinalizer!T()NoCalled during GC C#Finalizer~T()NoCalled during GC C#IDisposableDispose()No JavaFinalizerfinalize()NoCalled during GC

4 When Destructors Are Invoked ScenarioDestructor calledNotes Named automaticScope exit Free storedelete operatorPrior to memory being freed Statics and globalsProgram exitReverse order of construction Array elementsFrom last element to first STL container elementsUnspecified order TemporaryEnd of expression in which it was created If bound to reference or named object, when object exits scope Exception thrownStack unwinding Explicit dtorp->~T(); exit()For global & static objectsReverse order of construction abort()No; global & static dtors not called

5 Order of Destruction Rule of Thumb: Reverse order of construction Specifically: 1.Destructor body 2.Data members in reverse order of declaration 3.Direct non-virtual base classes in reverse order 4.Virtual base classes in reverse order

6 Destruction Order Example class Human : Ego, virtual Id {}; class Vulcan : Katra, Kolinahr {}; class Spock : Human, Vulcan { Tricorder t; Phaser p; }; Spock s; Spock Tricorder Phaser HumanEgoIdVulcanKatraKolinahr

7 Implicit Destructors Not specified by the programmer Inline by default Public Recommended for struct-like POD-only objects For everything else, avoid implicit destructors Better debugging Improved perf analysis

8 Trivial Destructors Destructors that never ever do anything Compiler can optimize away Requirements Implicit Not virtual All direct base classes have trivial dtors All non-static members have trivial dtors

9 Virtual Destructors Guarantee that derived classes get cleaned up Rule of thumb: if class has virtual functions, dtor should be virtual If delete on a Base* could ever point to a Derived* Perf: Obj with any virtual funcs includes a vtable ptr Idiom exceptions: mixin classes Pure signals abstract class virtual ~T() = 0 { }

10 Partial Construction & Destruction Dtors are only called for fully constructed objs If a ctor throws, obj was not fully constructed Object dtor will not be called But fully constructed subobjects will be destroyed Always use RAII within ctors Resource Acquisition Is Initialization

11 Virtual Functions in Destructors Virtual functions are not virtual inside dtors class Helmsman { public: // Red alert! virtual ~Helmsman() { Release(); } protected: virtual void Release() {} }; class Sulu : public Helmsman { … };

12 C++ Exception Handling Destructors : Exceptions :: Spock : Kirk Wrap any function that acquires a resource in a class where dtor releases the resource Never allow an exception to exit a dtor Best: dont throw in the dtor OK: wrap throwing code in a try/catch Good advice even if you dont use C++EH

13 Multithreading You are responsible for protecting objects and their contents Sharing an object across threads Use shared_ptr Or some other reference counting Or otherwise ensure only one thread can destroy Protect shared memory (global counters, ref counts) in dtors

14 delete and Destructors delete p is a two-step process. Pseudo code: // T* p = new T(…); T *p = (T*)operator new( sizeof(T) ); new (p) T(…); // placement new // delete p if( p != NULL ) { p->~T(); // explicit destructor operator delete( p ); }

15 Explicit Destructors Destructors can be called directly Avoid 99.99% of the time Very powerful for custom memory scenarios Example uses w/ placement new STL allocators void* p = Alloc(…); Kirk* pk = new (p) Kirk; pk->~Kirk(); Free( pk );

16 std::allocator Allocators enable custom STL container memory Two key destructive functions void allocator::destroy( T* p ) { ((T*)p)->~T(); } // default impl. void allocator::deallocate( T* p, size_type ) { operator delete( p ); } // default impl.

17 Case Study: std::vector template vector::~vector() { if( m_pFirst != 0 ) { for( T* p = m_pFirst; p != m_pLast; ++p ) m_Alloc.destroy( p ); m_Alloc.deallocate( m_pFirst ); }

18 shared_ptr Templated non-intrusive deterministically referenced-counted smart pointer Object Category Owned By Their Destroyed When AutomaticBlockControl Leaves Block Data MembersParentParent dies ElementsContainerContainer dies Dynamically Allocatedshared_ptrsAll shared_ptrs die shared_ptr sp( new T(…) );

19 Case Study: tr1::shared_ptr template shared_ptr::~shared_ptr() { if( m_pRep != NULL ) // if were not a NULL ptr { // and were the last owner if( InterlockedDecrement( &m_pRep->RefCount ) == 0 ) { // dispose of the shared object delete m_pSharedPtr; // use deleter if specified // if were done with the control block if( InterlockedDecrement( &m_pRep->WeakRefCount ) == 0 ) delete m_pRep; // use allocator.destroy if specified }

20 shared_ptr deleters Deleter: a functor called on the stored raw pointer when ref count hits zero template struct Deleter { void operator()( T* p ) { Free( p ); } }; Khan* p = Alloc(…); shared_ptr sp( p, Free ); shared_ptr sp( p, Deleter () );

21 Destructor Idioms to Love delete p if (p!=NULL) free(p) CloseHandle() DeleteCriticalSection() SetEvent() pComPtr->Release() --refCount InterlockedDecrement() flush() try { Close() } catch( … ) closesocket() assert( … ) { }

22 Destructor Gotchas: Red Alert delete a; delete b if( p != NULL ) delete p m_Handle = NULL Cleanup() m_Member.Cleanup() for( itr = v.beg(); itr != v.end(); ++itr ) delete *itr

23 Case Study: Multiple owned resources struct Uhura { X* p; Y* q; }; // Red alert: leak potential Uhura::Uhura() : p(new X), q(new Y) { } Uhura::~Uhura() { delete p; delete q; } struct Uhura { shared_ptr sp; shared_ptr sq; }; // Safe Uhura::Uhura() : sp(new X), sq(new Y) { } Uhura::~Uhura() {}

24 Performance Destructors are called a LOT Theyre invisible in code Streamline common dtors The best dtor is empty Inlining Profile }

25 Enterprise::~Enterprise() { } Case Study: Destructor Tuning Enterprise::~Enterprise() { Unload(); m_ReactorCore.Empty(); if( m_pOrdnance != NULL ) { delete m_pOrdnance; m_pOrdnance = NULL; } if( m_hAlert != NULL ) { CloseHandle(m_hAlert); m_hAlert = NULL; } for( int i = 0; i < m_CrewSize; i++ ) delete m_Crew[i]; } Enterprise::~Enterprise() { delete m_pOrdnance; if( m_Alert != NULL ) CloseHandle( m_hAlert ); for( int i = 0; i < m_CrewSize; i++ ) delete m_Crew[i]; }

26 Never own more than a single raw resource Never let any exceptions escape a dtor Never call virtual funcs from a dtor Avoid clearing data unnecessarily (e.g. zeroing memory, setting ptrs to NULL) Avoid implicit dtors for non-PODs Avoid dtors that call other member funcs Best Practices

27 Best Practices: Do This Embrace RAII: wrap any function that acquires a resource in a class where the dtor releases Embrace shared_ptrs to avoid leaks and deletes Virtual dtor iff delete Base* could be a Derived* Validate state in dtors: guaranteed choke point The best destructor: an empty destructor Second best: releasing a single resource

28 © 2009 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary. © 2009 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.


Download ppt "The Beauty of Destruction Pete Isensee Microsoft Game Developers Conference March 2009."

Similar presentations


Ads by Google