Symbian3/SDK/Source/GUID-F686965A-13E5-5C0A-AED1-55EC91C79433.dita
changeset 0 89d6a7a84779
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-F686965A-13E5-5C0A-AED1-55EC91C79433.dita	Thu Jan 21 18:18:20 2010 +0000
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-F686965A-13E5-5C0A-AED1-55EC91C79433" xml:lang="en"><title>Restrictions
+on the use of leaves and TRAPs in destructors</title><shortdesc>Outlines the restrictions on the use of leaves and TRAPs in destructors.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>You <i>cannot</i> use <xref href="GUID-3F2CDC74-2568-371C-9D8E-34A66A619226.dita"><apiname>TRAP</apiname></xref> (and <xref href="GUID-57895C34-AD00-35E1-9BF8-478653056383.dita"><apiname>TRAPD</apiname></xref>)
+and <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-ABF0FC5C-3334-3761-893D-D836B2EE0541"><apiname>User::Leave()</apiname></xref> in a destructor, nor in any function
+that a destructor might call, for objects that have been placed onto the call
+stack. <xref href="GUID-3F2CDC74-2568-371C-9D8E-34A66A619226.dita"><apiname>TRAP</apiname></xref> and <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-ABF0FC5C-3334-3761-893D-D836B2EE0541"><apiname>User::Leave()</apiname></xref> are implemented
+in terms of C++ Try, Catch and Throw. This means that if an exception occurs,
+the call stack is "unwound". In doing this, the destructors of objects on
+the call stack are called. If any of these destructors subsequently throw
+an exception, this is termed a nested exception. While a nested exception
+is supported on the emulator (WINS), it is not supported on other hardware,
+and there is no guarantee that the thread will terminate cleanly. </p>
+<p>Symbian coding standards state that objects placed onto the call stack
+should not have non-trivial destructors. By convention, such classes are identified
+by names having an initial T or R. This means that such destructors should
+not leave. </p>
+<p>The following code fragment shows the kind of code that is <i>not safe</i> to
+use: </p>
+<codeblock id="GUID-7B2BD496-6F99-5586-B320-DB7C5DC490B9" xml:space="preserve">void f()  
+    {
+    TBar bar;
+    // Function processing.
+    ...
+    // The bar object on the call stack is automatically destroyed
+    // at function termination.
+    }
+
+TBar::~TBar()
+    {
+    // The destructor calls a function that can leave.
+    // This is not permitted here.
+    doCleanUpL();
+    }</codeblock>
+<p>You <i>can</i> use <xref href="GUID-3F2CDC74-2568-371C-9D8E-34A66A619226.dita"><apiname>TRAP</apiname></xref> (and <xref href="GUID-57895C34-AD00-35E1-9BF8-478653056383.dita"><apiname>TRAPD</apiname></xref>)
+and <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-ABF0FC5C-3334-3761-893D-D836B2EE0541"><apiname>User::Leave()</apiname></xref> in a destructor and in any function that
+a destructor might call, for heap-based objects, i.e. objects that are destroyed
+by the cleanup stack. However, while this is permissible, it is not recommended
+practice. </p>
+<p>Such objects are instances of classes derived from <xref href="GUID-8F6FE089-E2A8-30F4-B67E-10F286347681.dita"><apiname>CBase</apiname></xref>,
+and by convention such classes are identified by names having have an initial
+C. </p>
+<p>In principle, a destructor should never fail. If a destructor can leave,
+or a function called by the destructor can leave, it suggests that the code
+has been poorly architected. It also implies that part of the destruction
+process might fail, potentially leading to memory or handle leaks. </p>
+<p>One possible approach to avoid using functions that can leave within a
+destructor is to have what might be referred to as ‘two-phase destruction’
+where some form of <codeph>ShutdownL</codeph> function is called prior to
+deleting the object. If there are concerns about introducing additional complexities
+in API-usage (and greater risk), suitable guards can be introduced. One method
+might be to store the current state of the object internally and then use
+an ASSERT to check this in the destructor. This would ensure that any usage
+errors are discovered by very simple run time testing. </p>
+<p>The following code fragment shows an example of two-phase destruction. </p>
+<codeblock id="GUID-BA3B57D6-913F-5AEC-A7AB-4EE6B915127A" xml:space="preserve">// Here, the shutdown function is a member of the class CMyClass,
+// and performs destruction activity that can leave.
+
+class CMyClass : public CBase
+    {
+public :
+    IMPORT_C ~CMyClass();
+    IMPORT_C void ShutdownL();
+    ...
+private :
+    TBool iStateActive
+    ...
+    }
+
+EXPORT_C void CMyClass::ShutdownL()
+    {
+       if (iStateActive == ETrue)
+              {
+              // Some destruction activity that can leave.
+              iStateActive = EFalse;
+              }
+    }
+
+EXPORT_C CMyClass::~CMyClass()
+    {
+       // Assert to ensure that ShutdownL() has already been called.
+       ASSERT(iStateActive == EFalse);
+    }
+</codeblock>
+</conbody></concept>
\ No newline at end of file