The two-phase structure is an important memory processing mechanism in Symbian and a required knowledge for Symbian software developers.
This article uses three questions and their corresponding answers to resolve the basic principles and usage of the second phase in Symbian, hoping to help you learn.
Question 1: Why do we need a two-phase structure?
Consider the following statement first:
Cclassname * PTR = new (eleave) cclassname ();
When there is sufficient space in the object, the code first allocates a cclassname object on the stack, assigns the address to the PTR pointer, and then calls the class constructor to initialize the object.
In this way, if an exception occurs in the class constructor, a problem occurs. When this exception occurs, no pointer is directed to the memory area successfully allocated to the cclassname object. Therefore, these memories become isolated memory, memory leakage occurs. This leads to an important rule for Symbian Memory Processing: the constructor cannot exit unexpectedly.
Question 2: Why can two-stage functions avoid Memory leakage?
The second-stage constructor, as its name implies, divides the construction of an object into two phases:
The first stage is a regular constructor. In this constructor, There is no code that may cause an exception to exit;
The second stage is the construction phase that may generate exceptions, implemented as the function constructl ();
In this way, the object construction process should include the following code:
Cclassname * Self = new (eleave) cclassname ();
Cleanupstack: pushl (Self );
Self-> constructl ();
Cleanupstack: Pop (Self );
Why can this constructor avoid Memory leakage? Next we will analyze the code line by line:
Cclassname * Self = new (eleave) cclassname ();
The overloaded new operator first allocates memory to the new self instance. If the allocation fails, the program exits unexpectedly. If the new object is successfully allocated memory, then execute the first-stage constructor that will not exit abnormally;
Cleanupstack: pushl (Self );
Next, we push the local pointer self into the clearing stack, because the following call may cause an exception to exit the function.
Self-> constructl ();
If the second-stage constructor exits abnormally during execution, the pointer of the new cclassname is clear from the stack to avoid Memory leakage. In addition, if the function does not exit abnormally, A fully constructed cclassname instance is created.
Cleanupstack: Pop (Self );
Securely pops up the local pointer from the clear stack;
Every time you instantiate an object, you must write the above Code. to simplify the instantiation process, Symbian OS introduces newl (), newlc () two functions (in fact, they can also be written as a newl (). However, we all recommend creating newl () and newlc () at the same time. For the specific implementation method, see question 3;
Question 3: how to create a two-stage constructor in a new class?
. H header file:
Class cclassname: Public cbase
{
Public:
Static cclassname * newl ();
Static cclassname * newlc ();
~ Cclassname ();
PRIVATE:
Cclassname (); // first-stage structure
Void constructl (); // second-stage structure
......
}
CPP source file:
Cclassname * cclassname: newl ()
{
Cclassname * Self = cclassname: newlc ();
Cleanupstack: Pop (Self );
Return self;
}
Cclassname * cclassname: newlc ()
{
Cclassname * Self = new (eleave) cclassname ();
Cleanupstack: pushl (Self );
Self-> constructl (); // Two-Phase Structure
Return self;
}
Void cclassname: constructl ()
{
/************** Code that may generate exceptions ************/
}
Source: http://blog.csdn.net/Atoric/archive/2008/05/26/2481631.aspx