`
yesjavame
  • 浏览: 687146 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

symbian的清除栈

阅读更多

symbian的清除栈

symbian是c++的子集,它基于C++但不需要C++所有的强大的功能,(事实上也不可能在手机这样的终端上实现
完整的C++所有功能).对于异常处理,symbian没有提供c++那样本地变量常异处理时显示调用析构函数的框架.
Symbian用自己清除栈来完成该工作.

1.不使用清除栈的情况:
aFuntion(){
CBar *pBar = new (ELeave) CBar;
pBar->FooL();
delete pBar;
}

由于FooL是一个可能"离开"(暂时用"离开"来翻译Symbian的错误Leave机制)的调用,一旦发生异常离开,则
delete pBar不能被执行,因为变量pBar本身aFunction的自动变量,会自动清除,但它指向的对象就永远留在了
堆中.经常重启手机的用户可能不多.

清除栈的思想是对于需要在异常离开后必须销毁的对象放入清除栈中,一量发生"离开",则异常处理系统会负
责将栈中的对象可靠地销毁,简言之它是一个需要手动控制的垃圾回收器.需要回收的对象需要手动加入,而且
只有在发生异常时才会自动销毁,否则这些对象一直在栈中,需要手工出栈并销毁.

最常用的模式:

aFunction(){

CBar *pBar = new (ELeave) CBar;
CleanupStack::PushL(pBar);
pBar->FooL();
CleanupStack::Pop();
delete pBar;

}
当pBar对象被构造后,立即被放入清除栈.下面pBar->FooL();调用如果出现异常离开了aFunction函数,因为清除栈

中还保存了变量本身的副本,它和变量pBar指向同一对象,所以它能通过这个变量副本清除掉这个堆上的对象.
如果不出现异常则程序继续向下执行:
CleanupStack::Pop();
delete pBar;
这两句,也就是如果没有发生异常则要手动处理栈中的对象,对于不需要清除栈来保证清除的时候主应该及时

出栈并处理.
因为 CleanupStack::Pop(); delete pBar;非常多地在一起使用,它们被合并成一个函数:
CleanupStack::PopAndDestroy(pBar);


那么什么样的对象需要放入清除栈中保护呢?
如上所述,一个函数中C类的自动变量,除了这个函数中的这个本地指针外,再也没有其它指针指向那个对象,一
旦这个指针随异常离开函数而消失,则它所指的对象就永远留在了堆中,这样的指针需要进入清除栈.

对于不需要析构的T类,一般不需要放入清除栈,除非发生这样特殊的调用:
Txx x = new (ELeave)Txx;
一般来说很少需要在堆中分配T类.所以很少发生这样的调用.

对于R类总是和一个资源相关联,作为自动变量时,无论是在栈中还是在堆中创建,都需要在发生异常时已经构造

的R类需要调用Close方法或reset方法,所以自动变量的R类会经常放入清除栈.

作为一个对象的成员变量没有理由放入清除栈,而应该放在析构函数中执行delete操作.

虽然合理使用清除栈能保证发生异常时已经构造的对象被正确销毁,但有一种情况,清除栈无能为力.即一个对象
在构造到一半时发生异常,因为没有成功构造,当前无法放入清除栈中.那么前一半所点用的资源就无法释放.
由些,引用了另一个概念:二层构建

即在构造对象是第一阶段只做零初始化,不构造任何实际的操作.保证不会发生离开事件,所以在构造方法中除了
零初始化没有任何实际操作.这样产生一个对象的引用后就可以在清除栈中保存它的副本,然后进行第二阶段的再
进行实际的构造,这样一量发生异常清除栈中已经有了该对象的引用.可以进行必要的清除:

//第一阶段构造方法:
CTest:CTest(){
//memner = 0;
}

void CTest::ConstructL() {
//实际需要构造的对象.
}

然后通过两个静态方法 NewLC和NewL来获取实例:
CTest* CTest::NewLC()
{
CTest* self = new (ELeave) CTest; //虽然是new (ELeave)运行符,但实际根本不会离开.
CleanupStack::PushL(self);
self->ConstructL(); //此时如果发生异常,清除栈中已经有了self的指针副本,可以执行必要有清除.
return self;
}
一个LC的方法说明函数可能离开但已经使用了清除栈保护,这个方法就是调用以后引用已经放入清除栈了.不需要
再做Push操作.

当然NewLC的目的是为了防止对象构造时发生异常而不能清理,一旦构造成功返回了.我们在对它的引用时不再需要
清除栈的保护,这时需要手出栈,那么NewL就是完成这个操作的:

CTest* CTest::NewL()
{
CTest* self = CTest::NewLC();
CleanupStack::Pop(self);
return self
}

所以两阶段操作可以保证对象在构造的过程中发生异常时能被正确地清理.而提供NewLC函数的类一经构造就已经在
清除栈中了.我们只需要在必要时出栈并销毁就行了:

HBufC* welcom = CEikonEnv::Static()->AllocReadResourceLC(R_WELCOM_TEXT);
//可能离开的操作
CleanupStack::PopAndDestroy(welcom);

分享到:
评论

相关推荐

    Symbian异常三步曲

    Symbian通过清除栈机制,可以在异常发生时自动释放相关资源,避免内存泄露。 **使用清除栈**的场景通常是在执行可能抛出异常的代码之前,将非异常安全的对象压入清除栈。一旦异常发生,清理栈会自动遍历栈中的对象...

    Symbian OS 高效编程

    全书共分为21章,分别介绍了Symbian OS中的类命名约定、异常退出、清除栈、两段构造、描述符、良好的描述符风格、动态的数组与缓冲区、使用活动对象的事件驱动多任务、活动对象、 Symbian OS的线程与进程、客户/...

    symbian泡泡龙游戏源码

    【标签】"symbian S60 C++ 游戏 源码"进一步明确了技术栈。S60是Symbian OS的一个用户界面框架,C++是Symbian平台的主要开发语言,这要求开发者具备C++基础知识,了解Symbian SDK和EPOC(Embedded Operating System...

    SYMBIAN OS C++高效编程.part1.rar

    全书共分为21章,分别介绍了Symbian OS中的类命名约定、异常退出、清除栈、两段构造、描述符、良好的描述符风格、动态的数组与缓冲区、使用活动对象的事件驱动多任务、活动对象、Symbian OS的线程与进程、客户/...

    SYMBIAN OS C++高效编程.part2.rar

    全书共分为21章,分别介绍了Symbian OS中的类命名约定、异常退出、清除栈、两段构造、描述符、良好的描述符风格、动态的数组与缓冲区、使用活动对象的事件驱动多任务、活动对象、Symbian OS的线程与进程、客户/...

    Symbian OS C++高效编程

    24420.6 编译器生成的函数 24520.7 小结 246第21章 良好的编码风格 24821.1 减小代码尺寸 24821.2 小心地使用堆内存 25021.3 小心地使用栈内存 25421.4 消除子表达式,最大化代码效率 25621.5 推迟...

    从ANSI C++到Symbian C++

    - **概念**:清除栈是一种机制,用于在程序执行过程中自动清理资源。 - **作用**:在Symbian OS中,这种机制对于确保资源的正确释放至关重要,特别是在处理有限的系统资源时。 ##### 3.5 两阶段构造 - **定义**:...

    Symbian的官方开发讲义(中文版)-Symbian_OS_-类型和声明

    值得注意的是,当T类对象在堆上创建时,为防止异常情况下内存泄漏,对象地址会被压入清除栈,一旦发生异常,内存会被自动回收,但不会调用析构函数。 此外,Symbian OS中还有对类命名的约定,通常使用T、C、R或M...

    Symbian 的 CBase类内幕-六个本质的问题.doc

    1. **为什么清除栈有3个PushL()版本,包括PushL(CBase *aPtr)?** 清除栈(CleanupStack)是一个关键的异常处理机制,用于确保在异常发生时正确清理资源。它提供了三个PushL()版本:PushL(TAny *aPtr)、PushL(CBase ...

    Symbian OS基础知识

    本文档旨在介绍Symbian OS 编程的基础知识,包括对象的创建和析构、命名约定、错误处理和清除、描述符以及活动对象等内容。 #### 2. 对象的创建与销毁 **2.1 基本概念** 面向对象编程是Symbian OS 的核心特性之一...

    symbian 2nd 俄罗斯方块源码

    对于游戏逻辑部分,源码会展示如何使用C++的数据结构和算法来实现方块的生成、旋转、下落和消除。这通常涉及到数组、栈或队列等基本数据结构,以及动态规划或贪心算法等编程技巧。通过分析源码,我们可以学习到如何...

    symbian s60连连看游戏源代码,大家快来下吧

    源代码中会有一个函数用于实现这一逻辑,可能涉及到递归或者栈结构。 4. **消除动画**:消除一对图案时,通常会有动画效果,如淡出、缩小等。这需要利用Symbian的动画框架,或者自定义绘制函数来实现。 5. **游戏...

    Symbian系统开发教程2.docx

    T 类的对象可以在栈上创建,当程序流程退出函数或产生 leave(一种代码异常)的时候,系统自动清除它。即使 T 类有一个析构方法,在发生异常(在 Symbian 系统中,异常被称为 leave)时 Symbian 系统也不会调用它,...

    Symbian OS Explained Effective C++ Programming for Smartphones

    - **21.3 小心使用栈内存**: 讨论了栈内存的使用限制及其对程序性能的影响。 - **21.4 消除子表达式以最大化代码效率**: 提供了优化代码结构的方法,以减少不必要的计算和提高运行效率。 #### 书籍特色 - **深度...

    Symbian 文件操作

    使用RFileWriteStream时,先调用`Replace()`创建输出流,接着`PushL()`将其推入清除栈,然后可以向流写入数据。完成写入后,调用`CommitL()`提交数据,最后使用`Pop()`和`Release()`或`CleanupStack::PopAndDestroy...

Global site tag (gtag.js) - Google Analytics