异常退出(Leave) Symbian OS的异常

      由于Symbian OS所强调的是简洁的操作系统和客户代码,异常退出(Leave)是用于取代相对开销较大的C++异常处理,以节省其所增加之运行时的存储器开销,以及编译出的代码大小。

  在编译基于Symbian OS的代码时,编译器禁止C++异常处理,所有使用trycatchthrow关键字的地方将被报错。  

  在异常退出时容易发生内存泄露。

 

      1、异常退出函数的定义

    异常退出函数中可能发生异常,函数名后加“L”。一般来说,除非需要将函数中所分配资源的指针或引用作为返回值,否则异常退出函数无返回值。

  当发生异常退出时,抛出异常同时产生一个错误代码,沿栈传递至异常捕获模块将其“捕获”。异常退出通过TRAP宏将栈指针指向捕获异常的context,然后由捕获模块来跳转到特定的程序位置,并恢复寄存器的值。从而,整个过程相当于:代码执行到异常退出点停止,然后返回到异常被捕获的地方。

 

  函数可能发生异常退出的情况:

   (1)调用可能异常退出的代码而未在其周围使用异常捕获模块;

   (2)调用一个会产生异常退出的系统函数;

   (3)使用了以Eleave为参数的new操作符重载形式。例如:CClanger* clanger = new (ELeave) Cclanger(); 该重载形式增加了一个隐式的Tleave类型的参数,使当堆上内存不足时,操作符发生Leave

 

  2、异常退出函数的使用

  异常退出处理的系统函数:

  (1)User::LeaveIfError():其参数为一个整数值,若其小于0,产生Leave,并将该参数作为异常退出码。用于需要返回非Symbian OS标准错误码;

  (2)User::Leave():不检查,直接产生以整数参数为异常退出码的Leave

  (3)Use::LeaveIfNull:以一个指针值为参数,参数为NULL时产生以KerrNoMemory为异常退出码的Leave

 

  构造函数与析构函数是不允许异常退出的。若允许构造函数失败,则应采用两段构造法以避免异常退出;而析构函数本身就由异常退出引起,若再发生Leave则会导致上个Leave不成功,如果有失败的可能,则应使用一个单独的Leave函数在析构前。

 

  使用异常处理函数时,要注意:对堆上的对象,就使用清除栈解决其可能在Leave后的内存泄露问题;而对栈上的对象,必须保证该对象是无析构函数的,即为T类或R类的对象。

 

3、使用TRAPTRAPD捕获异常

  TRAPD (result, MayLeave() );    //相当于已定义了result

  Tint result;

  TRAP (result, MayLeave() );    //与上面的等价

  即用于跟踪MayLeave()中产生的异常,并将异常代码号保存在result中,作为参数传递给User::Leave()系统函数。

  有时当在同一函数中多次或嵌套使用TRAP,可考虑给其整体加一个函数名,用一个TRAP解决问题,见书P17第二例。对应用程序开发来说,其框架自动提供一个最外层的TRAP

 

  不应轻易使用将错误码作为返回值的方式,而应使用异常退出,这样代码更小而易于维护。使用异常可以将正常执行流程与错误处理流程明确的分开,使用返回错误方案会带动来TRAP的开销。

  使用TRAP是一种昂贵的处理异常退出的方法,影响可执行文件尺寸与代码执行速度,应尽量减少使用。但每个程序中至少应该有一个TRAP来捕捉所有发生的异常退出。

 

4、LeaveScan

  用于检查源代码的每一行,确保不是以L结尾的函数都不会发生异常退出,带有L后缀的函数,确实可能发生异常退出。

你可能感兴趣的:(框架,OS,user,Symbian,编译器,程序开发)