诗剑书生的专栏

我在灌江口上住,花开花落,不知流年度.雁过空遗秋色暮,抚琴细听梧桐雨. 轻舞残虹漫展书,云卷云舒,思愫万千缕.安得婵娟与共处,长作识字耕田夫.                   诗剑书生 于灌江口.听潮居

诗剑书生ID:axman
105737次访问,排名829(-1)好友0人,关注者8
一个男人. 一个写程序男人. 一个写程序并从程序中寻找快乐的男人. 一个写程序并从程序中寻找快乐又把快乐传递给大家的男人.
一个书生. 一个寂寞的书生. 一个寂寞的梅香竹影下敲声写韵的书生. 一个寂寞的梅香竹影下敲声写韵晨钟暮鼓中逸气扬剑的书生.
那个男人是位书生。没有人知道他的姓名,居无定所,行无定踪,亦耕亦读,或渔或樵。
axman的文章
原创 87 篇
翻译 0 篇
转载 0 篇
评论 162 篇
axman的公告
最近评论
axman:不用说明什么,一切都如我预料的那样.
在整个奥运开幕式期间,我一边看电视,一边访问
http://www.cctvolympics.com/main.php?type=vod这个地址,其间访问一百多次,没有一次成功.大多数时候是前端缓存的squid在报refuse(111).有时以过几分钟的等待,能出来页面,但Flash缓冲的进度条到了99%就一直停止在那儿.
……
myvicc:写得不错,等写下文
chinagavin:我是先读三位正向输出,然后再读三位反向输出来最终达到想要的结果。
chinagavin:更新啊,好久没更新了。
YuLimin:快更新呀。。。等着呢:)呵呵。。。
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 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);
     

    发表于 @ 2006年09月22日 18:14:00|评论(loading...)|编辑

    新一篇: 多线程编程的设计模式 不变模式(一) | 旧一篇: 多线程编程的设计模式 临界区模式(三)

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © axman