--- /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