Symbian OS本身就是为内存和资源受限的设备开发的,应用程序运行过程中很可能碰到内存用光,或者硬件资源不可用的情况。而这种exceptions是通过修改程序无法解决的,所以遵守以下几条:

•尽量不要使用不必要的RAM 
•尽早释放资源,如文件server等 
•当你每次申请内存时,都须准备处理out-of-memory错误 
•当 out-of-memory错误发生时,返回到一个stable的状态,并释放所有期间申请到的资源 
Stack and Heap
    Stack:默认大小8kb,自动删除,如 TInt i = 0;

    Heap :至少0.5Mb,由程序员手动删除,如 CMyObj* obj = new (ELeave) CMyObj;


Leaves
    首先介绍Conventional C++ Memory Management,在Symbian看来,这是非常低效率的。

•NULL Pointer Checking  if ((myObj = new CMyObj( ) ) == NULL) { //Error Handling }

•ANSI C++ Exeption Handling   try { //throw an Exception } catch (int e) { //Error Handling }

    在Symbian中推荐采用Leave,如果内存或者资源不能分配到,这个代码就会Leave,沿着Call Stack,直到操作系统或者在某个函数中被Handle掉。

    所有可能Leave的函数最好以L结尾,保证该函数的用户知道这个函数可能Leave。

    Leave的例子:

•动态内存分配: return new (ELeave) TUint8[1000]; 
•产生一个Leave:User:eave(KErrNotFound); 
•内存不足时Leave:User:eaveNoMemory(); 
•NULL的时候Leave:User:eaveIfNull(aNotify); 
•当发生错误时Leave:RFs fs; TInt err = fs.Connect(); User:eaveIfError(err);

    处理Leave:

    操作系统有默认的处理Leave的方式:

•在程序启动过程中:直接关闭应用程序。 
•应用程序启动后:显示一个错误消息。  
    开发者可以通过trap装置来处理Leave。TRAP(_r, _s)和TRAPD(_r, _s),其中:

•_r:是一个TInt类型的leave code,默认值为TErrNone。

•_s:一系列可能Leave的C++ Statements。

        TRAPD(err, DoFunctionL());
        if (err != KErrNone)
        { //Error Handling }
        else
        { //Everything is well }


  The Cleanup Stack
    cleanup stack用于存储在leave发生后需要deallocating的局部变量(指针)。即:当一个函数leave了,所有在cleanup stack上的对象会被全部删除掉。

    Cleanup Stack的使用方法:

CleanupStack:ushL(ptr) :当发生leave时所有内存都会被释放
CleanupClosePushL(handle):当发生leave时这个句柄(handler)会被关闭

CleanupStack:op(pointer):第一个元素出栈
CleanupStack:opAndDestroy(pointer):第一个元素出栈并释放内存

    如果一个函数可能leave,检查一下两种情况:

•如果leave了,是否所有在堆(heap)上的元素都在cleanup stack中了 
•如果没有leave,你是否自己恰当地将他cleanup了

CMyClass* CMyClass::NewL(TInt aBufSize)
{
   CMyClass* self = new (ELeave) CMyClass;
   CleanupStack:ushL(self);
   self->ConstructL(aBufSize);
   CleanupStack:op(self);
   return self;
}

    如果某个函数会在cleanup stack上留下一个对象,那么他必须以C结尾。

Two Phase Construction
    C++构造函数一定不能leave。所有内存和资源的分配应该在第二阶段构造函数ConstructL( )中完成。

编码指南,所有用户定义的C类必须:

•定义NewL和NewLC函数为public static 
•定义ConstructL和C++ Constructor为private

Best Practise

     Construction的规则:

•默认的C++构造函数中不能含有可能leave的代码 
•可能发生leave的函数必须在ConstructL中被调用 
•如果基类也有ConstructL,必须首先调用,不要忘了explicit scoping

    Destruction的规则:

•C类必须在析构函数中删除它自己所包含的对象 
•在删除一个对象后,把它的指针设为NULL 
•不要删除不是本类所拥有的对象 

•在reallocation前首先删除对象,并且将其指针设为NULL