All code that can leave shall be executed under a trap harness. If a leave occurs control will be returned to the most recent TRAP and a variable will contain the error code. It does not mean though that each and every leaving function should be executed under a trap harness. Leaving functions are executed by other leaving functions and it is only required that the function on the top of the call stack was trapped. You should use as minimun TRAP harness as possible in your program because it can affect your efficiency of your program.
There are three macros to trap a leave: TRAP, TRAPD, TRAP_IGNORE. They differ only in the way they deal with the leave code.
You need manually declare a variable for the leave code before using the TRAP macro:
TRAPD declares a variable in wich it returns the leave code itself:
TRAP_IGNORE does not require any variables and you do not get the leave code:
Where to put trap harness?
Exception_handling_in_Symbian_OS describes how to use trap harnesses more effectively.
Tips and tricks
Do not trap LC-functions
Be carefull with TRAPD
TRAPD declares a variable to contain the leave code every time. Consider the code below:
In this fragment we will always return the leave code of LeavingFunctionL(), because the second TRAPD redeclares err within the curly brackets which limit its scope. A workaround would be to use TRAP instead of TRAPD in the second case.
Try to optimize the use of traps
Traps have overheads that result in worse performance so it is advised to use trap macros very carefully. Consider the following example:
This three traps can be replaced with only one trap by adding one more function:
The result will be the same but the performance will be better.
Use trap instrumentation
If you have a look at e32cmn.h (located in \epoc32\include) you will find three interesting macros:
These macros allow to execute some code on every trap: TRAP_INSTRUMENTATION_START before the trapped code is invoked, TRAP_INSTRUMENTATION_NOLEAVE is executed if no leave occures, TRAP_INSTRUMENTATION_LEAVE is invoked in case of a leave.
To use the macros you need to redefine them. For example:
static void LogLeave(TInt aErr, const TUint8* aFile, TInt aLine);
#define TRAP_INSTRUMENTATION_LEAVE(aResult) LogLeave(aResult, (TText8*)__FILE__, __LINE__)
In this example the LogLeave() function will be invoked every time when a leave is trapped. The function arguments are here the leave code (error code), the source file name and the line number. So in case of a trapped leave you can get something like the line below in your log file.
Leave: -5, somesourcefile.cpp : 307
If you want to catch a leave where it happens (rather than in the place of the TRAPD), you can use the method described in Debugging Leaves in some circumstances.
You can use these macros when making your debug logger, see this page for good example of debuglogger: Trace Function Enter, Exit and Leave.