Symbian3/SDK/Source/GUID-F686965A-13E5-5C0A-AED1-55EC91C79433.dita
changeset 7 51a74ef9ed63
parent 0 89d6a7a84779
equal deleted inserted replaced
6:43e37759235e 7:51a74ef9ed63
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-F686965A-13E5-5C0A-AED1-55EC91C79433" xml:lang="en"><title>Restrictions
       
    13 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>
       
    14 <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>)
       
    15 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
       
    16 that a destructor might call, for objects that have been placed onto the call
       
    17 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
       
    18 in terms of C++ Try, Catch and Throw. This means that if an exception occurs,
       
    19 the call stack is "unwound". In doing this, the destructors of objects on
       
    20 the call stack are called. If any of these destructors subsequently throw
       
    21 an exception, this is termed a nested exception. While a nested exception
       
    22 is supported on the emulator (WINS), it is not supported on other hardware,
       
    23 and there is no guarantee that the thread will terminate cleanly. </p>
       
    24 <p>Symbian coding standards state that objects placed onto the call stack
       
    25 should not have non-trivial destructors. By convention, such classes are identified
       
    26 by names having an initial T or R. This means that such destructors should
       
    27 not leave. </p>
       
    28 <p>The following code fragment shows the kind of code that is <i>not safe</i> to
       
    29 use: </p>
       
    30 <codeblock id="GUID-7B2BD496-6F99-5586-B320-DB7C5DC490B9" xml:space="preserve">void f()  
       
    31     {
       
    32     TBar bar;
       
    33     // Function processing.
       
    34     ...
       
    35     // The bar object on the call stack is automatically destroyed
       
    36     // at function termination.
       
    37     }
       
    38 
       
    39 TBar::~TBar()
       
    40     {
       
    41     // The destructor calls a function that can leave.
       
    42     // This is not permitted here.
       
    43     doCleanUpL();
       
    44     }</codeblock>
       
    45 <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>)
       
    46 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
       
    47 a destructor might call, for heap-based objects, i.e. objects that are destroyed
       
    48 by the cleanup stack. However, while this is permissible, it is not recommended
       
    49 practice. </p>
       
    50 <p>Such objects are instances of classes derived from <xref href="GUID-8F6FE089-E2A8-30F4-B67E-10F286347681.dita"><apiname>CBase</apiname></xref>,
       
    51 and by convention such classes are identified by names having have an initial
       
    52 C. </p>
       
    53 <p>In principle, a destructor should never fail. If a destructor can leave,
       
    54 or a function called by the destructor can leave, it suggests that the code
       
    55 has been poorly architected. It also implies that part of the destruction
       
    56 process might fail, potentially leading to memory or handle leaks. </p>
       
    57 <p>One possible approach to avoid using functions that can leave within a
       
    58 destructor is to have what might be referred to as ‘two-phase destruction’
       
    59 where some form of <codeph>ShutdownL</codeph> function is called prior to
       
    60 deleting the object. If there are concerns about introducing additional complexities
       
    61 in API-usage (and greater risk), suitable guards can be introduced. One method
       
    62 might be to store the current state of the object internally and then use
       
    63 an ASSERT to check this in the destructor. This would ensure that any usage
       
    64 errors are discovered by very simple run time testing. </p>
       
    65 <p>The following code fragment shows an example of two-phase destruction. </p>
       
    66 <codeblock id="GUID-BA3B57D6-913F-5AEC-A7AB-4EE6B915127A" xml:space="preserve">// Here, the shutdown function is a member of the class CMyClass,
       
    67 // and performs destruction activity that can leave.
       
    68 
       
    69 class CMyClass : public CBase
       
    70     {
       
    71 public :
       
    72     IMPORT_C ~CMyClass();
       
    73     IMPORT_C void ShutdownL();
       
    74     ...
       
    75 private :
       
    76     TBool iStateActive
       
    77     ...
       
    78     }
       
    79 
       
    80 EXPORT_C void CMyClass::ShutdownL()
       
    81     {
       
    82        if (iStateActive == ETrue)
       
    83               {
       
    84               // Some destruction activity that can leave.
       
    85               iStateActive = EFalse;
       
    86               }
       
    87     }
       
    88 
       
    89 EXPORT_C CMyClass::~CMyClass()
       
    90     {
       
    91        // Assert to ensure that ShutdownL() has already been called.
       
    92        ASSERT(iStateActive == EFalse);
       
    93     }
       
    94 </codeblock>
       
    95 </conbody></concept>