There are two places in Symbian OS where you can create objects:
the heap and the program stack.
In Symbian OS, classes that are intended to be instantiated on the heap
are nearly always derived from the CBase class. This class gives you
two things:
? zero initialization, so that all data members, member pointers and
handles are initially zero
? a virtual destructor, so that the object can be properly destroyed.
This is an important point when we come to look at cleanup
issues later.
All CBase derived classes must be placed on the heap, but
that not all heap objects are necessarily CBase derived.
CMyClass* myPtr = new (ELeave) CMyClass;
myPtr->Foo(); // can safely access member data & functions
...
delete myPtr;
The main difference here is that we have specified ELeave as part of
the new operation. What this means is that instead of returning a NULL
value when there isn’t enough memory in which to create the CMyClass
object, the operation ‘leaves’.
***C++ delete does not set the pointer to zero. If you delete any
member object from outside its class’s destructor, you must set the
member pointer to NULL.
that stack objects in Symbian OS shouldn’t be too big, and they should
only be used for small data items – for example, strings of a few tens of
characters, say. Taking string data as an example, a good rule of thumb is
to put anything larger than a file name on to the heap. However, it’s quite
acceptable to put pointers (and references) onto the stack – even pointers
to very large objects.
You can control the stacksize in a .exe, through the use of the
epocstacksize keyword of the .mmp file used to create the .exe.
However, this only applies to console programs, servers or programs
with no GUI – and not to GUI programs as they are launched with
apprun.exe. GUI programs have a small program stack, of the order of
20k, and must be considered a valuable resource.
The type of objects that can go on to
the stack are:
? any built-in type: these are given typedefs, such as TInt for a
signed integer.
? any enumerated type, such as TAmPm, which indicates whether a
formatted time-of-day is am or pm. Note that all enumeration types
have names starting with a T, though enumerated constants such as
EAm or EPm begin with E.
? class types that do not need a destructor, such as TBuf<40> (a buffer
for a maximum of 40 characters) or TPtrC (a pointer to data, or to a
string of any number of characters). TPtrC contains a pointer, but it
only uses (rather than has) the characters it points to, and so it does
not need a destructor.
堆内都是最后需要进行销毁的,栈上的都是 不需要销毁内容,因为他们没有数据。
The pattern here is __ASSERT_ALWAYS(condition, expression), where
the expression is evaluated if the condition is not true. Before attempting
to execute the code, we make sure that the parameter aIndex is positive,
and panic with code EMyAppIndexNegative if not.
OutOfMemory :Cleanup Framework
Programing error :Panic Handling
Enviroment error :Leave
We could have done this without the aid of the cleanup stack by using
code like this:
case ECleanupCmdUse3:
{
CX* x = new(ELeave) CX;
TRAPD(error, x->UseL());
if(error)
{
delete x;
User::Leave(error);
}
delete x;
}
However, this is much less elegant. The cleanup stack works particularly
well for a long sequence of operations, such as:
case ECleanupCmdUse3:
{
CX* x = new(ELeave) CX;
CleanupStack::PushL(x);
x->UseL();
x->UseL();
x->UseL();
CleanupStack::PopAndDestroy();
}
You only need to put a pointer to an object on to
the cleanup stack to prevent an object’s destructor from being bypassed.
If an object is a member variable of another class (rather than an
automatic like x), then it will be destroyed by the class’s destructor,
so you should never push a member variable to the cleanup stack.
The cleanup stack and C++ destructors make it very easy for a
programmer to handle cleanup. Use the cleanup stack for objects
pointed to only by C++ automatics. Use the destructor for objects
pointed to by member variables. It just works. You very rarely
need to use TRAP(). The resulting code is easy to write, compact,
and efficient.
It’s a fundamental rule of Symbian OS programming that no C++
constructor should contain any functions that can leave.
The distinction between T, C and R is very important in relation
to cleanup. In general, T classes don’t require cleanup because they
allocate no resources, R classes acquire resources that need to be closed
or released, and C classes need to be deleted.
This is different from the size
of the descriptor, which is the number of bytes occupied by the data;
length and size are not necessarily the same. For example, the length of a
descriptor containing a string of five Unicode characters is 5, but the size
is 10 bytes.
A heap descriptor is an HBufC type, and you use this where a
malloc()’d cell would be used in C. This is the only class in Symbian
OS whose name begins with H.These types are useful when the amount of
data may be too big for a buffer descriptor, or where the data to be held by
the descriptor cannot be determined until runtime.
A pointer descriptor is a TPtr type or a TPtrC type; a TPtrC can be
used where a const char* would be used in C.引用
A buffer descriptor is a TBuf type or a TBufC type, and they can be
used where a char[] would be used in C.字符串
You may have noticed that buffer descriptors and pointer descriptors both
come in two types: TBufC and TBuf, TPtrC and TPtr.
We use the C in the type names to mean constant or non-modifiable.
The TBuf/TPtr types differ from the TBufC/TPtrC types by having an
extra machine word that contains the maximum length that the descriptor
data can expand to.
The heap descriptor is slightly different. It is allocated as a single cell
from the heap. To save memory, the length of the data area is implied by
the length of the underlying heap cell. When memory is allocated from
the heap, the length of a heap cell is usually rounded up to a value that
depends on the underlying hardware. This means that you can end up
with a descriptor that’s slightly bigger than one you asked for.