|
|
|
|
TRAPFunctions that leave, including functions that call other functions that can leave, must be executed under a trap harness.
If a call to User::Leave() occurs within the function,
control will immediately be returned to the most recent TRAP. A
variable is used with every trap to receive the error code specified in a
leave.
If no leave occurs, then when the called function ends, execution
returns to the TRAP, and the leave variable has the value
KErrNone.
Typically after a TRAP, a function checks the leave
variable to test whether processing returned normally or by leaving, and acts
appropriately. Special mechanisms discussed later are provided to handle
cleanup after the exception.
TInt E32Main()
{
testConsole.Title(); // write out title
testConsole.Start(_LIT("Example")); // start a new "test"
// The leave variable
TInt r;
// Perform example function. If it leaves,
// the leave code is put in r
TRAP(r,doExampleL());
// Test the leave variable
if (r)
testConsole.Printf(_LIT("Failed: leave code=%d"), r);
testConsole.End(); // finish
testConsole.Close(); // close it
return KErrNone; // and return
}
It is not necessary that all L functions be directly invoked by a trap harness. In most cases, functions that can leave are called normally by other functions. It is only necessary that somewhere above the function in the call chain is a trap harness.
It is not recommended to call a function with an LC
suffix from inside a trap harness. This is because if the function does not
leave, the object that the function created and pushed onto the cleanup stack
will remain on the cleanup stack on exiting from the trap harness. This causes
a E32USER-CBase 71 panic, unless the object is popped by the
caller from within the trap harness, for example:
TRAPD(error, pointer = SomeClass::SomeFunctionLC(); CleanupStack::Pop(pointer));
In this code, if SomeClass::SomeFunctionLC() leaves,
then pointer is destroyed as part of leave processing. If it does
not leave then CleanupStack::Pop(pointer) is called, avoiding the
panic.