Symbian exception handling

Introduction to the trap and leave mechanism used in Symbian code instead of standard C++ exceptions.

Leaves are lightweight exceptions

A leave is equivalent to throwing in standard C++ exception handling. Like C++ exceptions, leaves are used to propagate errors to where they can be handled.

A leave may occur in a function if it:
  • calls one of the functions in class User that cause a leave, such as User::Leave() or User::LeaveIfError().

  • uses the Symbian overloaded form of operator new, which takes ELeave as a parameter, and there is insufficient remaining memory to allocate the object.

  • calls another function that may leave (for either of the reasons above) without using a TRAP harness.

There is a naming convention to indicate the potential for a leave within a function. If a function may leave, its name must end with a trailing L. This convention is strictly adhered to in Symbian code.

Handling a leave using TRAP or TRAPD

The TRAP and TRAPD macros correspond to the try and catch {…} of C++ standard exception handling. You place a call to a function that may leave inside a TRAP harness and then test whether the function resulted in a leave. For example:
// Declare and intitialize a variable to store
// the leave code generated by MayLeaveL().
TInt result = KErrNone;

// Wrap the call to the leaving function 
// inside a trap harness.
TRAP( result, MayLeaveL() );

// Check result to find out if a leave
// occurred.
if ( result != KErrNone )    
   {    
   // Test for individual leave values
   // and handle as appropriate.
   }
The TRAP and TRAPD macros differ only in that TRAPD declares and initializes the variable in which the leave error code is returned. So the code above could be rewritten more simply:
// The variable result is automatically declared and 
// initialized to KErrNone by the TRAPD macro.
TRAPD( result, MayLeaveL() );

if ( result != KErrNone )    
   {    
   ...
   }
TRAP macros can be nested to catch and handle leaves at different levels, where they can best be dealt with. This allows you to propagate an error from its point of detection to a handler higher up the function call chain without needing to add conditional logic to the intermediate functions. Each TRAP has an impact on executable size and execution speed, so the number of traps should be minimized.

Comparing a leave and a panic

All leaves generated within an application should ultimately be trapped to ensure that errors are handled gracefully. A leave that is not trapped will cause the thread to terminate, resulting in poor user experience. The Qt and AVKON application frameworks contain a top-level trap in the main application thread.

In contrast, a call to the static function User::Panic() cannot be caught and handled. A panic always terminates the thread in which it is occurs. Panics are only useful for tracking down programming errors during development. The most common use of panics is inside a call to __ASSERT_DEBUG, which is equivalent to the assert macro used in C and C++ code.

Copyright note

Some of the material in this topic is based with permission on a Symbian Foundation wiki article Leaves and the Cleanup Stack which is part of the series The Fundamentals of Symbian C++. The version used was that available at http://developer.symbian.org/ on 3 November 2010. The content in this page is licensed under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License (http://creativecommons.org/licenses/by-sa/2.0/uk).

Related concepts