|
规则 2:使用清除堆栈
为何需要清除堆栈(Cleanup Stack)
如果某个函数出现了异常,就立即将控制返回给在其中调用它的 TRAP模块。一般说来,默认的TRAP量都被销毁了。然而,如果这些自动变量中的任何一个是指向堆中已分配对象的指针,就会产生问题。当发生异常退出并销毁了这个指针时,被指向对象就悬空了,从而产生内存泄漏。
例如:void doExampleL()
{ CSomeObject* myObject1 = new (ELeave) CSomeObject; CSomeObject* myObject2 = new (ELeave) CSomeObject;// WRONG }
在这个范例中,如果成功创建了 myObje ct1 ,但却没有足够的内存空间可分配给 myObject2 ,myObject1就会在堆中悬空。
这样,我们就需要某些机制来保留这类指针,以便让其所指向的内存在异常退出后得到释放。Symbian OS 在清除堆栈中为此目的提供了一种机制。
使用清除堆栈
清除堆栈中含有一些指针,它们指向所有当发生异常退出时需要释放的对象。这意味着:所有 C-类(C-class)对象都由自由变量而不是实例数据所指向。当发生异常退出时,会弹出 TRAP或 TRAPD宏,并销毁从 TRAP起始时推入到该清除堆栈中的一切东西。
所有的应用程序都有自己创建的清除堆栈。(应用程序框架在图形用户界面应用中自动创建了一个。)典型的情况是:所有的应用程序将至少有一个对象被推入到清除堆栈中。我们用 Clea nupStack::PushL()将对象推入到清除堆栈中,而用 CleanupS tack::Pop()将其弹出。如果位于清除堆栈中的那些对象不再有机会因异常退出而悬空,就必须将这些对象弹出。通常在释放该对象之前会发生异常退出。我们一般使用 P opAndDestroy(),而不是 Pop(),因为前者将确保该对象在弹出的同时被释放掉,从而避免释放前发生异常退出及内存泄漏。
拥有指向其他 C-类(C-class)对象指针的复合对象必须在其解构器中被释放掉。因此,并不需要将任何由另一个对象的成员数据(而不是一个自动变量)所指向的对象推入到清除堆栈中。事实上,一定不要将其推入到清除堆栈中,否则当发生异常退出时它就会被销毁两次:一次由解构器,另一次由这个TRAP宏。
规则 3:两阶段构造
有时候,某个构造函数需要分配资源,如内存。最普遍的情况就是某个复合 C-类(C-class):如果某个复合类含有一个指向另一个 C-类(C-class)的指针,它就需要在自己的构造过程中为那个类分配内存。   [1] [2] 下一页
|