NewLC()– a new type of constructor in Symbian C++?

I am in the phase of learning Symbian C++ and Symbian OS, so this is the moment in time when I ask myself many questions about how the things are done.

Everywhere you will read a Symbian programming tutorial you will find a topic about the two phase construction. What exactly is this?

As I wrote in one of my previous posts the memory is a scarce resource when talking about mobile software development. You will have to be careful to code your application keeping in mind that memory needs to be handled very accurately. In general, in embedded programming you do not afford, like when doing PC desktop software development, to have any memory leak or a dangling pointer.

What is a memory leak? It is when you destroy a pointer to a memory location which was not freed correspondingly. The memory location is said to be left “orphaned”, there is no pointer to it so it cannot be handled inside the program.

What is a dangling pointer? Is a pointer that is used to indicate some data which was previously released. A common example is when you return a pointer from a function and that pointer indicates a local variable. A common workaround to avoid such dangling pointer bugs is to lock the pointer to NULL value after it released a resource.

Since in Symbian a lot of applications are relying on C classes (classes derived from CBase class), which are instantiating objects only on the heap, dynamically memory allocation will be intensively used.

One rule of thumb in Symbian is that the constructor is not allowed to leave. OK…

But what if your class contains data pointing to other classes, like you would have the situation below

Class CSimple : public CBase
{
public:

    CSimple(Tint);
    void function();

private:

    Tint iVal;


}

Class CCompound : public CBase
{
public:

    CCompound(Tint);

private:

    Tint iVal;
    CSimple *iCSimple;

}

You may observe the CCompound owns data to other classes, as is iCSimple pointer. If you will instantiate a CCoumpound object, like this:

CCompound *test = new(ELeave) CCompound();

You will need to call CCompoud constructor which will have to handle iCSimple pointer also, because is totally indicated not to leave the pointers unallocated, and, after all, this is its duty, to initialize class members. The initialization of iCSimple will look something like this:

CCompound::CCompound (Tint aVal)
{

    iVal=aVal; // a part of CCompound objects is correctly initialized
    iCSimple = new(ELeave) CSimple(aVal); // on its turn CCompound calls CSimple >> what if a leave occurs here

}

Nothing until here is unfamiliar to a C++ programmer, things are obvious, a class has a member a pointer to another class. When initializing that pointer, the constructor of the other class is called. Actually there are two stages, one in which memory is allocated and the other in which memory is initialized. Allocation happens in new and initialization in the constructor.

What if allocating a CSimple object via iCSimple provokes a leave? Part of a CCompound object was created, I am referring to iVal, but the object cannot be finalized due to a leave event. In one of my earlier posts I wrote that there are three situations in which a leave may occur:

  1. when a function designed to produced a leave is called,
  2. when a function calls code that can, on its turn to leave,
  3. and when allocation with new(ELeave) is done.

This example is the second case when a function (CCompound constructor in this case) calls code (new (ELeave)) that may leave.

This is a very clear situation which shows that during the construction phase of an object in Symbian, one part may leave and other may not. I think this is the driving reason of introducing the two-phase construction.

What is the difference between having pointers to the same class and pointers to other classes as members? What is the reason that I gave an example of a class having as member a pointer to another class and not the same class?

The answer is simple and quite straightforward. If a class owns resources only to itself, potentially leaves are handled at the moment the object is created.

If CCompound would be like this

Class CCompound : public CBase
{
public:

    CCompound(Tint);

private:
Tint iVal;
CSimple *iCCompound; //instead of *iCSimple
}

And

CCompound::CCompound (Tint aVal)
{

    iVal=aVal;
    iCCompound= new(ELeave) CCompound(aVal);

}

The potential leave needs to be handled when object is created
CCompound *test = new(ELeave) CCompound(aVal);

… and this will be done via TRAPS or CleanuUp Stack.

Coming back to the example of CCompound constructor, this needs to be split in two parts, one that is guaranteed not to leave and the other calling the overloaded form of new(ELeave) operator. So this part

iCSimple = new(ELeave) CSimple(aVal);

needs to be stripped away from the CCompound implementation and treated somewhere else. It will be replaced by what is commonly referred as leaving part of a constructor or ConstructL() function. This will be handled via NewL and NewLC constructors like this.
CCompound class and constructor will look like this:

class CCompound: public CBase
{
public:

    static CCompound* NewL();
    static CCompound* NewLC();
    ~CCompound();

...
private:

    CCompound(); // Guaranteed not to leave.
    void ConstructL(); // Second-phase construction code, may leave.
    CSimple* iCSimple;

};

And NewLC and NewL will have the following implementation:

CCompound* CCompound::NewLC()
{

    CCompound* self = new (ELeave) CCompound(); // First-phase construction.
    CleanupStack::PushL(self);
    self ->ConstructL(); // Second-phase construction.
    return (self);

}

CCompound* CCompound::NewL()
{

    CCompound* self = CCompound::NewLC();
    CleanupStack::Pop(self);
    return (self);

}

You can clearly see above that the part that will leave is separately implemented in NewLC constructor and that it is used a self CCompound pointer to call ConstructL function. In this way a CCompound object either is completely created (both parts, the one that cannot leave and the one that may leave, are allocated on the heap) either is not created at all, if self pointer allocation via new(ELeave) fails, the CCompound object will not be allocated and any resources pointing to it will be correctly freed.

Advertisements

3 Responses to NewLC()– a new type of constructor in Symbian C++?

  1. Brustler says:

    I advise you to use Deleaker ( http://deleaker.com/ ) to avoid memory leaks in C++

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: