一,Symbian程序编程规范

 

1,  类名、函数名、常量的第一个字母大写

2,  类成员变量、函数形参第一个字母小写

3,  函数名以大写L结尾表示函数在执行时可能会产生异常

4,  宏命名必须以下划线开头,并且名字中各个单词用下划线隔开

5,  枚举名称以T开头

6,  类名通常以C、T、M、R开头

C开头的类,都从CBase继承而来,C类的所有对象只能放在堆上。

T开头的类,是普通类,如Tint、TUInt等,该类的所有对象既可以在栈上也可以在堆上

M开头的类,只表示一个接口,只包含纯虚函数

R开头的类,是资源类

 

二,Symbian OS 的内存处理机制

1,  TRAP和TRAPD

2,  清理栈

3,  两阶段构造函数

自己对三者的理解:

1,  TRAP和TRAPD同C++中的catch{}try差不多,TRAP和TRAPD有一个out参数err,

举个例子 : Tint err ;  TRAP( err , B())

如果函数B()没发生异常,err就会被赋值0 ,否则返回非0

     我们就可以根据err值进行异常处理。TRAP和TRAPD并不能对函数B中的内存泄漏

      进行处理。但是清理栈可以解决这个问题。

2,  以B函数为例,清理栈主要是解决在B函数中申请的内存但在B函数后面(还是在 B函数中)的代码出现异常,显然如果我们没有Push,之前申请的内存就会泄漏,如果用push 就会解决这个问题。

3,  两阶段构造函数,是为了解决在构造函数中为成员变量赋值失败而产生内存泄漏(此时类对象已经在堆上申请了内存空间。

我试想用TRAP和清理栈来代替两阶段构造函数。

两阶段构造函数:

      A*A::CreateL()

      {

         A* m = new ((ELeave)A ;   (1) 第一层构造函数

         Cleanupstack::PushL(m) ;  

         m->CreL() ;      (2)第二层构造函数

         Pop(m)

}

 A::CreL()

 {

    n = new (Eleave)B ;

    Cleanupstack::PushL(n) ;

    MMML()

  Pop(n) ;

}

 

如果用TRAP代替:

A::A()

{

   PushL(this) ;

   n = new (Eleave)B ;

} ;

 

Void MMM()

{

   Tint err ;

   A *a = 0 ;

   Trap(  err , a = new A ) ;

   If( !err)

   {

        Pop(a) ;

   }

}

 

问题:

 

MMML()

{

}

 

class Test1:public CBase

{

} ;

 

class CTest:public CBase

{

  public:

        Tint m ;

        Test1 * n ;

        CTest() ;

        static CTest * MCreateL() ;

        Test1 * ML() ;

} ;

 

CTest * CTest::MCreateL()

{

 

    CTest *q =  new (ELeave)CTest ;(1)

    Cleanupstack::PushL(q) ;       (2)

    q->ML() ;

    Cleanupstack::Pop() ;

    return q ;

}

 

Test1 * CTest:ML()

{

   n = new (ELeave)Test1 ;

   Cleanupstack::PushL(n) ;

   MMML() ;

   Cleanupstack::Pop() ;

}

 

 

 

 

CTest::CTest()

{

   m = 0 ;

}

 

void Cmen()

{

   CTest *q =  CTest::MCreateL(); 

   CleanupStackStack::PopAndDestroy() ;

}

 

问题1:在(1)中不会产生异常,所以认为(2)行可以去掉

       解决:这种想法是错误的,之所以用PushL(),是为了防止其后面的代码会发生异常而产生内存泄漏

             跟前面行是否发生异常没有关系。

             另外最美好的设计模式是PushL()和Pop()在同一个函数中,这样可以避免自己(或他人)在别的

             地方调用Pop()或是PopAndDestroy()时产生错误(因为别人并不知道在其他函数中已经Push过,

             而没有Pop。

 

问题2:CleanupStackStack::PopAndDestroy() 是不是在任何一个程序中都必须有?

       解决:不是,当发生了异常,那么只是执行了Push,而没有Pop ,最后程序会自动将栈中对象删除。

 

 

posted on 2010-07-13 20:58  liuze  阅读(287)  评论(0编辑  收藏  举报