Symbian OS - Memory Management

6,324 views

Published on

This tutorial is a thorough introduction to the important concepts related to memory management in Symbian OS. Detailed examples explain the reasons behind the concepts and give advice on what you have to do to develop a safe application for Symbian OS.

Contents:

* Leaves, Panics and TRAPD
* Cleanup Stack
* Object construction using ELeave
* Two-phase construction
* Debugging tools

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,324
On SlideShare
0
From Embeds
0
Number of Embeds
52
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Symbian OS - Memory Management

  1. 1. Symbian OS<br />Memory Management<br />v2.0a – 21 May 2008<br />1<br />Andreas Jakl, 2008<br />
  2. 2. Disclaimer<br />These slides are provided free of charge at http://www.symbianresources.com and are used during Symbian OS courses at the University of Applied Sciences in Hagenberg, Austria ( http://www.fh-hagenberg.at/ )<br />Respecting the copyright laws, you are allowed to use them:<br />for your own, personal, non-commercial use<br />in the academic environment<br />In all other cases (e.g. for commercial training), please contact andreas.jakl@fh-hagenberg.at<br />The correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials.<br />Parts of these materials are based on information from Symbian Press-books published by John Wiley & Sons, Ltd. This document contains copyright materials which are proprietary to Symbian, UIQ, Nokia and SonyEricsson. “S60™” is a trademark of Nokia. “UIQ™” is a trademark of UIQ Technology. Pictures of mobile phones or applications are copyright their respective manufacturers / developers. “Symbian ™”, “Symbian OS ™” and all other Symbian-based marks and logos are trademarks of Symbian Software Limited and are used under license. © Symbian Software Limited 2006. <br />Andreas Jakl, 2008<br />2<br />
  3. 3. Schedule<br />Leaves, Panics and TRAP(D)<br />Cleanupstack<br />ObjectconstructionusingELeave<br />Two-phaseconstruction<br />Debugging tools<br />Andreas Jakl, 2008<br />3<br />
  4. 4. Leaves & Panics<br />Handling problems<br />Andreas Jakl, 2008<br />4<br />
  5. 5. Exceptions – Java<br />Try & Catch for handling exceptions<br />Functions can throw “Exceptions”<br />Andreas Jakl, 2008<br />5<br />Integer Class<br />…<br />static intparseIntthrowsNumberFormatException {<br />…<br />}<br />…<br />Calling function<br />Try {<br />int x = Integer.parseInt(“1234”);<br />} catch (NumberFormatException e) {<br />System.out.println(“Unable to convert this String to a number.”);<br />}<br />
  6. 6. Leave – Symbian<br />TRAP(D) catches exceptions (“Leave”)<br />Functions send out leave<br />Function name marked by an L-suffix<br />Andreas Jakl, 2008<br />6<br />The TRAP(D) macros are defined in e32cmn.h<br />Main-Function<br />TRAPD(err, DoExampleL());if (err) { console-&gt;Printf(KTxtFailed, err); }<br />DoExampleL()-Function<br />voidDoExampleL() {RFsfsSession; // Connect to the file serverUser::LeaveIfError(fsSession.Connect()); // …fsSession.Close(); }<br />TRAPD-Makro declares err as TInt and = KErrNone<br />Leaves if the Connect() function does not return KErrNone<br />
  7. 7. Central ExceptionHandling<br />Andreas Jakl, 2008<br />7<br />New (ELeave) …<br /> … NewL() …<br /> … User::Leave() …<br />… ConstructL() …<br />F6L()<br />F7L()<br />F8L()<br />F9L()<br />F5L()<br />F5L() …<br /> … F6L() ….<br />… F8L() ….<br />F3L()<br />F4L()<br />F0L()<br />F2L()<br />… F3L() …<br />F4L() …<br />F1L()<br />TRAPD(err, F2L());<br />if(err) …<br />
  8. 8. Handling Leaves<br />Try to implement central leave-handling<br />If leave not handled by your code  error-message shown by the UI-framework!<br />Therefore: Only handle leaves yourself if they influence your application<br />Andreas Jakl, 2008<br />8<br />
  9. 9. When can a function leave?<br />Caused by your own code:<br />User::Leave(), User::LeaveIfError(), User::LeaveNoMemory() or User::LeaveIfNull()<br />Failed object-construction<br />when using the “new (ELeave)”-operator<br />Calling a function that potentially causes a leave<br />e.g. x-&gt;DoSomethingL()<br />Andreas Jakl, 2008<br />9<br />
  10. 10. Details: Causing a Leave<br />User::Leave(TIntaReason)<br />Error code (aReason) = value that will be received by TRAP<br />Causes leave in any case<br />User::LeaveIfError(TIntaReason)<br />Causes leave if parameter is negative, e.g.:TIntfoundAt = iElementArray.Find(example, aRelation);User::LeaveIfError(foundAt); // Leaves if foundAt == KErrNotFound (-1)<br />User::LeaveNoMemory()<br />Is the same as: User:Leave(KErrNoMem);<br />User::LeaveIfNull(TAny* aPtr)<br />Andreas Jakl, 2008<br />10<br />
  11. 11. TRAP / TRAPD<br />Two trap harness macros:<br />TRAP: declares the variable in which the leave code is returned<br />TRAPD: declare a TIntvariable yourself<br />If a leave occurs inside MayLeaveL(), which is executed inside the harness, the program code will return immediately to the TRAP harness macro<br />The variable result will contain the error code associated with the leave or will be KErrNoneif no leave occured<br />Andreas Jakl, 2008<br />11<br />TRAPD(result, MayLeaveL());<br />if (KErrNone!=result)<br />...<br />is equivalent to:<br />TIntresult;<br />TRAP(result, MayLeaveL());<br />if (KErrNone!=result)<br />...<br />
  12. 12. Tips<br />Andreas Jakl, 2008<br />12<br />X<br />voidInsertData()<br /> {<br />TInt err;<br /> TRAP(err, iData-&gt;InsertL(23));<br />if (err) { ... }<br /> TRAP(err, iData-&gt;InsertL(24));<br />if (err) { ... }<br /> }<br />TRAPs are expensive<br />Don’t use several TRAPs right after each other<br />Instead:<br />Make the function leave (append an L to the function name)<br />Handle all errors in a single TRAP-call one level above!<br />In UI apps, many leaves don’t have to be handled by you  they can go up to the topmost level (= Active Scheduler)<br />prefer<br /><br />voidHandleCommand()<br /> {<br /> TRAPD(err, InsertDataL());<br />if (err) { ... }<br /> }<br />voidInsertDataL()<br /> {<br />iData-&gt;InsertL(23));<br />iData-&gt;InsertL(24));<br /> }<br />
  13. 13. Panics<br />... cannot be caught and handled!<br />Terminates thread (= usually the whole application)<br />Use them for checking code logic only<br />Can also be sent out by the system for critical errors<br />If a panic happens:<br />Make sure you fix it, as you can’t handle it!<br />Andreas Jakl, 2008<br />13<br />// Stray signal detected!<br />_LIT(KMsgStraySignal, &quot;Stray signal &quot;);<br />User::Panic(KMsgStraySignal, 1); // Panic with code 1<br />
  14. 14. Resource Handling<br />Stack, Heap and the Cleanup Stack<br />Andreas Jakl, 2008<br />14<br />
  15. 15. Practice in a Nutshell<br />All strategiesarepresent in thisfunction:<br />Andreas Jakl, 2008<br />15<br />CClass* CClass::NewL(TIntaInt, CBase& aObj)<br />{<br />CClass* self = new (ELeave) CClass(aInt);<br />CleanupStack::PushL(self);<br />self-&gt;ConstructL(aObj);<br />CleanupStack::Pop(self);<br />returnself;<br />}<br />
  16. 16. Recap: Stack<br />Andreas Jakl, 2008<br />16<br />// Stack (1)<br />voidCTest::F1()<br />{<br />TInt x = 0;<br />TInt y = 1;<br />for(x = 0; x &lt; 10; x++)<br /> y++<br /> y = y + F2(); <br />// Stack (4)<br />}<br />// Stack (5)<br />TIntCTest::F2()<br />{<br />TInt a = 2;<br />TInt b = 1;<br />return a + b; // Stack (3)<br />}<br />Stack (2)<br />Stack<br />(5)<br />Stack<br />(1)<br />TInt y<br />TInt x<br />F1<br />Stack<br />(2)<br />TInt y<br />TInt x<br />F1<br />Stack<br />(4)<br />TInt b<br />TInt a<br />F2<br />TInt y<br />TInt x<br />F1<br />Stack<br />(3)<br />
  17. 17. Recap: Heap<br />Use for:<br />Objects that need a lot of memory ( stack-size is limited!)<br />Required amount of memoryonlyknown at runtime<br />Scope of heap-objects is not limited to a function<br />Use pointers to pass to other functions/objects<br />Andreas Jakl, 2008<br />17<br />
  18. 18. Motivation<br />Symbian OS designed to run for many years<br /> No opportunity to reclaim leaked memory through regular restarts!<br />Small memory leaks accumulate over time<br />We only have a small memory to start with<br />Therefore: Simply write perfect, leak-free code!<br />Andreas Jakl, 2008<br />18<br />
  19. 19. Motivation – How?<br />By keeping track of all allocated objects!<br />By making sure:<br />All heap-objects are pointed to by at least one pointer, all the time – even in the constructor of an object!<br />Free heap memory as soon as possible after use.<br />Andreas Jakl, 2008<br />19<br />
  20. 20. The Cleanup Stack<br />Safeguard<br />Andreas Jakl, 2008<br />20<br />
  21. 21. Resource Handling – Rule 1<br />Andreas Jakl, 2008<br />21<br />Every local pointer to an instance of a heap-based object also has to be pushed on the cleanup stack, if there‘s the risk that the pointer gets lost because of a leave.<br />
  22. 22. Cleanup Stack<br />Situation: function creates local heap-object<br />Before code gets to the delete-statement: error<br />Function is left (Leave)<br />Pointer-address on the stack is freed<br />Object itself is orphaned memory leak!<br />Andreas Jakl, 2008<br />22<br />voidCImage::DoSomethingDangerousL()<br /> {<br /> User::Leave(KErrNotFound);<br /> }<br />CImage<br />voidCMyObj::DoSomethingL()<br />{<br />}<br />CImage* img = new (ELeave) CImage();<br />img-&gt;DoSomethingDangerousL();<br />deleteimg;<br />img = pointer on the stack to an instance on the heap<br />
  23. 23. Cleanup Stack<br />Memory situation if a leave occurs:<br />Andreas Jakl, 2008<br />23<br />!<br />X<br />X<br />img<br />Heap<br />Stack<br />Object stays on the heap;Pointer to delete the instance is lostmemory leak<br />
  24. 24. Cleanup Stack<br />Solution: Cleanup Stack<br />Andreas Jakl, 2008<br />24<br />void CMyObj::DoSomethingL()<br />{<br />CImage* img = new (ELeave) CImage();<br />CleanupStack::PushL(img);<br />img-&gt;DoSomethingDangerousL();<br />CleanupStack::PopAndDestroy();<br />}<br />img<br /><br />CleanupStack<br />X<br />X<br />img<br />Heap<br />Stack<br />When no leave occurs: object still has to be deleted by you + removed from the cleanup stack!<br />Cleanup stack saves a second pointerto the object on the heap.<br />
  25. 25. AdvancedCleanup<br />Andreas Jakl, 2008<br />25<br />RFile<br />Forresourcesthathavetobeclosed / freed(e.g.: files, sockets, …)<br />Close(): CleanupClosePushL(T&)<br />Release(): CleanupReleasePushL(T&)<br />Destructor: CleanupDeletePushL(T*)<br />Close()<br />TCleanupOperation<br />TAny* aPtr<br />…<br />TCleanupItem<br />CleanupStack<br />
  26. 26. AdvancedCleanup – Example<br />Andreas Jakl, 2008<br />26<br />voidCMyClass::TransferDataL()<br /> {<br />RSocketServsocketServer;<br /> // Connect to SocketServer<br /> User::LeaveIfError( socketServer.Connect() );<br /> // Make sure Close() is called at the end<br />CleanupClosePushL( socketServer );<br />// …<br />CleanupStack::PopAndDestroy(); // socketServer<br /> }<br />
  27. 27. Cleanup Stack and Ownership Transfer<br />It should never be possible for an object to be deleted more than once!<br />Andreas Jakl, 2008<br />27<br />voidTransferOwnershipExampleL()<br /> {<br /> // The stack variable ptr points to memory allocated on the heap<br />CItem* ptr = new (ELeave) CItem();<br /> // The following function may leave -&gt; place the pointer on the<br /> // cleanup stack, so that the heap memory is freed in case <br /> // AppendL() leaves.<br />CleanupStack::PushL(ptr);<br /> // iItemPtrArray takes ownership of the CItem object.<br /> // This could fail, as it needs to allocate a new slot to store the pointer, <br /> // therefore the object was placed on the cleanup stack in advance<br />iItemPtrArray-&gt;AppendL(ptr);<br /> // iItemArray now owns the heap object, so ptr may be safely popped off the stack.<br /> // It shouldn’t be destroyed, as this would make the item in iItemPtrArray invalid!<br />CleanupStack::Pop(ptr);<br /> }<br />
  28. 28. Practice in a Nutshell<br />Strategiesexplaineduptonow:<br />Andreas Jakl, 2008<br />28<br />CClass* CClass::NewL(TIntaInt, CBase& aObj)<br />{<br />CClass* self = new (ELeave) CClass(aInt);<br />CleanupStack::PushL(self);<br />self-&gt;ConstructL(aObj);<br />CleanupStack::Pop(self);<br />returnself;<br />}<br /><br /><br />
  29. 29. Resource Handling – Rule 2<br />Andreas Jakl, 2008<br />29<br />Never push instance variables on the cleanup stack!<br />The owning class is also on the cleanup stack somewhere (at least indirectly). This would lead to a double deletion of the object pointed to by the instance variable  Panic!<br />
  30. 30. Coding Error Example<br />Andreas Jakl, 2008<br />30<br />class CSimple : CBase<br /> { <br />public:<br /> ~CSimple();<br /> void MayLeaveFuncL();<br />private:<br /> void PrivateMayLeaveL();<br />CItem* iItem;<br /> };<br />CSimple* simple = new (ELeave) CSimple();<br />CleanupStack::PushL(simple);<br />1. CSimple is created and pushed onto the cleanup stack as the next function may leave<br />TRAPD(res,simple-&gt;MayLeaveFuncL());<br />...<br />2. A leaving method is called on simple<br />void CSimple::MayLeaveFuncL()<br /> {<br />iItem= new (ELeave) CItem();<br />CleanupStack::PushL(iItem);<br />PrivateMayLeaveL();<br />CleanupStack::Pop(iItem);<br /> }<br />3. The member variable is pushed onto the clean up stack (oops!)<br />5. The TRAP does the right thing and clears the cleanup stack; i.e. CSimple::iItem is deleted <br />4. What happens if a leaves occurs? <br />...<br />6. The code logic completes with the popping and deleting of the simple object.<br />CleanupStack::PopAndDestroy(simple);<br />CSimple::~CSimple<br /> {<br /> delete iItem;<br /> }<br />BUT this calls the CSimple destructor, which deletes the iItem which has already been deleted by the TRAP <br />7. PANIC!<br />Example taken from theSymbian Academy slides<br />
  31. 31. Object Construction<br />Leave-handling during<br />Andreas Jakl, 2008<br />31<br />
  32. 32. New Objects<br />new-operator allocates memory and runs constructor<br />Returns null-pointer if object creation fails(e.g. not enough memory)<br /> manual test required to see if it was successful – no automated leave!<br />Andreas Jakl, 2008<br />32<br />void CMyObj::DoSomethingL()<br /> {<br />CImage* img = newCImage();<br /> if (img) <br /> {<br />CleanupStack::PushL(img);<br />img-&gt;DoSomethingDangerousL();<br />CleanupStack::PopAndDestroy();<br />} <br /> else<br /> {<br /> User::LeaveNoMemory();<br /> }<br /> }<br />
  33. 33. New Objects – ELeave<br />Andreas Jakl, 2008<br />33<br />void CMyObj::DoSomethingL()<br /> {<br />CImage* img = newCImage();<br /> if (img) <br /> {<br />CleanupStack::PushL(img);<br />img-&gt;DoSomethingDangerousL();<br />CleanupStack::PopAndDestroy();<br />} <br /> else<br /> {<br /> User::LeaveNoMemory();<br /> }<br /> }<br />void CMyObj::DoSomethingL()<br /> {<br />CImage* img = new (ELeave)CImage();<br />CleanupStack::PushL(img);<br />img-&gt;DoSomethingDangerousL();<br />CleanupStack::PopAndDestroy();<br /> }<br />identical<br />new-Operator overloaded with ELeave:<br />automated leave if there’s not enough memory!<br />
  34. 34. Practice in a Nutshell<br />Strategiesexplained so far:<br />Andreas Jakl, 2008<br />34<br />CClass* CClass::NewL(TIntaInt, CBase& aObj)<br />{<br />CClass* self = new (ELeave) CClass(aInt);<br />CleanupStack::PushL(self);<br />self-&gt;ConstructL(aObj);<br />CleanupStack::Pop(self);<br />returnself;<br />}<br /><br /><br /><br />
  35. 35. Two-Phase Construction<br />The ultimate combination …<br />Andreas Jakl, 2008<br />35<br />
  36. 36. Resource Handling – Rule 3<br />Andreas Jakl, 2008<br />36<br />Neither a constructor nor a destructor may cause a leave!<br />The destructor must not assume that the object was fully initialized.<br />
  37. 37. Leaves in the Constructor<br />Andreas Jakl, 2008<br />37<br />1. Call to constructorof CEngine<br />Application<br />CEngine* myEngine = new (ELeave) CEngine();<br />…<br />…<br />CEngine<br />CEngine::CEngine() {<br />iList = new (ELeave) CList();<br />}<br />CEngine::~CEngine() {<br />deleteiList;<br />}<br />iList<br />CEngine<br />2. Leave – nomemory left for allocating iList<br />Heap<br />3. Because of the leavethere is no valid pointerto the partially constructedCEngine-object.<br />4. Without a validpointer, the memoryalready allocatedfor CEngine is lost.<br />?<br />
  38. 38. Solution: Two-phase Construction<br />Andreas Jakl, 2008<br />38<br /><br />Application<br />CEngine* myEngine = new (ELeave) CEngine();CleanupStack::Push(myEngine);<br />myEngine-&gt;ConstructL();<br />…<br />// Note that the following line won’t be // reached in case of a leave!CleanupStack::PopAndDestroy(myEngine);<br />CEngine<br />CEngine::CEngine() {// 1. Phase<br />}<br />CEngine::ConstructL() {// 2. Phase<br />iList = new (ELeave) CList();<br />}<br />CEngine::~CEngine() {<br />deleteiList;<br />}<br />iList<br />CEngine<br />Heap<br />Object is fully allocated and on the cleanup stack  the destructor can be executed, the class is deleted by the cleanup stack  all memory is properly cleaned up in case of a leave!<br />
  39. 39. Simplification: Two-phase Construction<br />Less complicated creation of objects:<br />Trailing C at the end of the function name: an object is left on the cleanup stack (as in NewLC())<br />Andreas Jakl, 2008<br />39<br />CEngine<br />CEngine* CEngine::NewLC() {CEngine* self = new (ELeave) CEngine(); // 1. PhaseCleanupStack::PushL(self);<br /> self-&gt;ConstructL(); // 2. Phase<br />return self;<br />}<br />CEngine* CEngine::NewL() {<br />CEngine* self = CEngine::NewLC();<br />CleanupStack::Pop(self);<br />return self;<br />}<br />Application – Local Variable<br />CEngine* myEngine = CEngine::NewLC();<br />…<br />CleanupStack::PopAndDestroy(myEngine);<br />or<br />Application– Instance Variable<br />iMyEngine = CEngine::NewL();<br />Destructor:<br />delete iMyEngine;<br />Application – Instance variable<br />iMyEngine = CEngine::NewL();<br />// Destructor:<br />deleteiMyEngine;<br />
  40. 40. Practice in a Nutshell<br />Strategiesexplained so far:<br />Andreas Jakl, 2008<br />40<br /><br />CClass* CClass::NewL(TIntaInt, CBase& aObj)<br />{<br />CClass* self = new (ELeave) CClass(aInt);<br />CleanupStack::PushL(self);<br />self-&gt;ConstructL(aObj);<br />CleanupStack::Pop(self);<br />returnself;<br />}<br /><br /><br /><br /><br /><br />
  41. 41. Derivation<br />Note:<br />Some thoughts are necessary when deriving from a class that uses two-phase construction<br />See the literature or Symbian Academy-slides for details!<br />Andreas Jakl, 2008<br />41<br />
  42. 42. Resource Handling – Rule 4<br />Andreas Jakl, 2008<br />42<br />If memory for a pointer (instance variable) is reallocated, set the old pointer to NULL beforehand.<br />
  43. 43. NULL<br />Situation (without NULL):<br />AllocL() causes a leave, which propagates up …<br />Instance of CElement is deleted<br />Destructor of CElement is called<br />iName still points to already deleted memory<br />Deleted 2x  Panic<br />Andreas Jakl, 2008<br />43<br />voidCEngine::DoStuffL(constTDesC& aName)<br /> {<br />CElement* element = CElement::NewLC();<br /> TRAPD(err, element-&gt;SetNameL(aName));<br />CleanupStack::PopAndDestroy(element); <br /> }<br />2<br />1<br />voidCElement::SetNameL(constTDesC& aName)<br /> {<br />deleteiName; // Deletes object, does not change pointer<br />iName = aName.AllocL(); // Re-Allocation<br /> }<br />voidCElement::~CElement()<br /> {<br />deleteiName;<br /> }<br />1<br />2<br />iName = NULL; // Deletes pointer on stack<br />Note: delete does not delete a NULL pointer.<br />
  44. 44. Summary<br />Andreas Jakl, 2008<br />44<br />
  45. 45. Summary<br />Catch leaves (= exceptions) with TRAP(D)<br />Use cleanup stack for local heap-based variables<br />Do not use the cleanup stack for instance variables<br />No leaves in constructors or destructors<br />Use two-phase construction for objects with data on the heap<br />Set a pointer to NULL before re-allocating memory<br />Andreas Jakl, 2008<br />45<br />!<br />
  46. 46. What’s wrong?<br />Andreas Jakl, 2008<br />46<br />CleanupStack::PushL(iList);<br />
  47. 47. What’s wrong?<br />Andreas Jakl, 2008<br />47<br />CleanupStack::PushL(iList);<br />Never push instance variables on the cleanup stack!<br />Twice as safe isn’t safe at all…<br />
  48. 48. What’s wrong?<br />Andreas Jakl, 2008<br />48<br />CEngine* engine = new (ELeave) CEngine();…CleanupStack::PopAndDestroy(engine)<br />
  49. 49. What’s wrong?<br />Andreas Jakl, 2008<br />49<br />CEngine* engine = new (ELeave) CEngine();…CleanupStack::PopAndDestroy(engine)<br />enginewasn‘t pushed on the cleanup stack!new (ELeave) is only responsible for leaving if memory allocation for the object fails. new (ELeave) has nothing to do with the cleanup stack.<br />Solution: Either: add the object to the cleanup stack:<br />CleanupStack::PushL(engine);<br />Or: don’t use the cleanup stack for deleting – in case no leaving operation is called between creation and deletion of the engine object:<br />delete engine;<br />
  50. 50. What’s wrong?<br />Andreas Jakl, 2008<br />50<br />voidCGomokuViewGame::ChangeViewContextText(TIntaResourceId)<br /> {<br />RBufnewText(iEikonEnv-&gt;AllocReadResourceL(resourceId));<br />newText.CleanupClosePushL ();<br />MQikViewContext* viewContext = ViewContext ();<br /> // Changing an alreadyexistingviewcontexttext<br />viewContext-&gt;ChangeTextL (EGomokuViewContext, newText);<br />CleanupStack::PopAndDestroy (1); // newText<br /> }<br />
  51. 51. What’s wrong?<br />Andreas Jakl, 2008<br />51<br />void CGomokuViewGame::ChangeViewContextText(TInt aResourceId)<br /> {<br /> RBuf newText(iEikonEnv-&gt;AllocReadResourceL(resourceId));<br /> newText.CleanupClosePushL ();<br /> MQikViewContext* viewContext = ViewContext ();<br /> // Changing an already existing view context text<br /> viewContext-&gt;ChangeTextL (EGomokuViewContext, newText);<br /> CleanupStack::PopAndDestroy (1); // newText<br /> }<br />The trailing L of the function name is missing, as calls within<br />the function can leave.<br />Solution:void CGomokuViewGame::ChangeViewContextTextL(…)<br />
  52. 52. Testing your Code<br />On your way to perfection<br />Andreas Jakl, 2008<br />52<br />
  53. 53. Macros for Testing<br />Wrap code you want to test within __UHEAP_MARK and __UHEAP_MARKEND:<br />Andreas Jakl, 2008<br />53<br />CClass* p1 = new (ELeave) CClass;<br />__UHEAP_MARK;// Mark start of test-area<br />CClass* p2 = new (ELeave) CClass;<br />CClass* p3 = new (ELeave) CClass;<br />__UHEAP_CHECK(2);// 2 Objects (p2, p3) on the heap since the start-mark<br />__UHEAP_CHECKALL(3);// In total 3 objects on the heap<br />delete p3;<br />_UHEAP_MARKEND;// Result: p2 is still here – Memory Leak!<br />// or: __UHEAP_MARKENDC(1);// Expects one cell on the heap<br />
  54. 54. Finding Memory Leaks<br />Emulator checksheapautomaticallyifyouexittheprogram BEFORE closingtheemulatorwindow!<br />Andreas Jakl, 2008<br />54<br />Find it in theSymbian OS SDK doc:<br />Symbian OS SDK v…  Symbian OS guide  Symbian OS reference  System panicreference<br />
  55. 55. Memory Information<br />Show numberofallocatedcells:<br />Ctrl+Alt+Shift+A<br />Andreas Jakl, 2008<br />55<br />
  56. 56. Allocation Failure<br />Intentional failing of memory allocation:<br />__UHEAP_SETFAIL(aType, aValue);<br />EDeterministic: fail every nth request<br />ERandom: fail randomly once within a specified range – always using the same seed<br />ETrueRandom: random seed taken from system time<br />Andreas Jakl, 2008<br />56<br />__UHEAP_SETFAIL(RHeap::EDeterministic, 2);<br />CObj* c1 = new (ELeave) CObj; // will allocate<br />CObj* c2 = new (ELeave) CObj; // will fail<br />CObj* c3 = new (ELeave) CObj; // will allocate<br />CObj* c4 = new (ELeave) CObj; // will fail<br />__UHEAP_RESET; // Deactivate<br />
  57. 57. FAILNEXT<br />Fails thenextallocationrequest<br />Andreas Jakl, 2008<br />57<br />CObj* c1 = new (ELeave) CObj; // will allocate<br />__UHEAP_FAILNEXT(1);// failnextallocation<br />CObj* c2 = new (ELeave) CObj; // will fail<br />
  58. 58. AllocationFailure<br />In theemulator, withoutwritingcode:<br />Heap Failure Tool<br />Activate:Ctrl+Alt+Shift+P<br />Deactivate:Ctrl+Alt+Shift+Q<br />Can failheap, WindowServer-allocationsorfile-access<br />Andreas Jakl, 2008<br />58<br />
  59. 59. … let’s move to the Challenges!<br />Try it for your own<br />Andreas Jakl, 2008<br />59<br />

×