What are “leaves” in Symbian programming?

I’ve published several weeks ago an article highlighting the Symbian C++ coding conventions. One of the most important was the suffix: L. When a function is suffixed with L, actually this is informing the run-time machine that this function will generate an exception.

Actually leaves are Symbian equivalent of C++ exceptions. Suffixing a function with an L is like testing it into a try C++ clause.

Typically leaving functions  perform operations that are not guaranteed to succeed. A good example of this would be a memory allocation. Due to the fact that a Symbian equipped smartphone is relying on limited hardware resources, it may often happen that insufficient memory conditions occur. Just remember about the heap overflow discussion that I had in my dynamic memory allocation posts. On top of this you may add the notorious stack overflow issue.

It is very important to suffix a function that you “suspect” to leave because callers of this code may defend themselves against a potentially leak memory. An un-trapped leave may generate a panic, which is an error that results in blocking the entire system, in other words, is an untrapped error.

But how should you know whether or not a function will leave?


One possibility would be to call a system function which will produce a leave. In this case you are explicitly generating the leave, such functions in Symbian are User::Leave(), User::LeaveIfError()

Another possibility would be to use the Symbian C++ overloaded form of new operator, which takes ELeave as parameter.  If the memory to allocate for that object is insufficient, heap-overflow exception is provoked so the program will … leave .

There is a long discussion about how to allocate objects and data in Symbian: whether on the stack whether on the heap. As I already said few words about this in another Symbian-related post, usually objects of T classes are allocated on the stack (or can be allocated on the stack) and those of C classes are allocated on the heap (actually must always be allocated on the heap). This is another discussion and I hope it will make the subject of a future post.

But let’s just stop a little bit at this point and discuss about the overloaded new operator. Why Symbian needs such an operator?

Because this acts as a regular C++ new operator but in addition it leaves in case no memory is available.

So it is not needed to make the check on new for a SUCCES or FAILURE return condition, this thing is implicitly accomplished by new(ELeave). By this, some extra code required for testing if the allocation was successful, is not needed anymore. The new operator, overloaded in order to receive Eleave as parameter, leaves in case if no memory is available, that’s why no check is required.

We saw how can a leave occur, but why are they so bad?

… because they can generate memory leaks and in the context of limited resources of mobile smarphones  Symbian is deployed to, this can become critical. One memory leak here, another there and chances that the overall system may crash increase drastically.

How can leaves generate memory leaks?

Just have a look at the code below:

void UnsafeFunctionL()
{

    // Allocates test on the heap
    CTestClass* test = new (ELeave) CTestClass();
    test->FunctionMayLeaveL();
    // test is a local pointer that holds the address of a CTestClass
    //in case FunctionMayLeaveL leaves, object pointed by test is not freed anymore
    //after program returns from the leave handler, test - a local pointer - will be deleted
    // and the memory that it points won't be freed
    delete test;

}

This thing is called, more or less academically, that the heap variables are orphaned by local pointers.

It can be  done a workaround to solve this. Symbian solves this issue via two macros, TRAP and TRAPD.  The difference between them is that TRAPD declares a variable which returns the error code, but TRAP doesn’t, the program has to define it.

TInt errorCode;
TRAP(errorCode, FunctionLeave1L());
if (KErrNone==errorCode){

    TRAPD(errorCode, FunctionLeave2L());

}
User::LeaveIfError (errorCode);

If FunctionLeave1L leaves the  returned code will be  stored in errorCode variable which is at the same scope level as TRAP macro. The problem occurs when second function, FunctionLeave2L, leaves. The errorCode is actually returned not in the right variable, the one that TRAPD overloads, but it is returned in the one defined with TInt. When this is read by User::LeaveIfError, this may provoke another leave even it should not be the case. So, in order to avoid misunderstandings or confusions about which function left and the error information that indicates this. Instead of TRAPD a TRAP needs to be defined.  In this case errorCode variable of former TRAPD won’t overload errorCode defined with TInt.

OK so you would say that this completely solves the issue of leaves. Well .. is not actually like this .. they (TRAP and TRAPD) have a serious impact in terms of execution speed and code size.  Calling a TRAP is somehow similar to an interrupt or context switch in terms of  overhead that they imply. The state prior to the call must be saved and then restored, making this TRAP/TRAPD mechanism a quite expensive way to manage a leave.

As you may already know from C++, exceptions or leaves, propagate through different levels in the program. A TRAP at the topmost level is required to catch any leave which was not handled before.

Another thing closely related to the leave mechanism in Symbian, is the Clean-up stack.  I will the pleasure of writing about such subject for another post, most probably next one Symbian-related

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: