关于symbian的清除栈

news/2024/7/3 14:56:04

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


http://www.niftyadmin.cn/n/2951681.html

相关文章

SVG入门-裁剪和遮罩

前言 擦除已经创建的元素的部分内容,最初看起来有点矛盾。但是如果你打算在SVG中创建一个半圆形,你将很快发现下面的属性的作用了。 Clipping用来移除在别处定义的元素的部分内容。在这里,任何半透明效果都是不行的。它只能要么显示要么不显…

SVG入门-基本变换

前言 SVG元素的形变都会用到一个元素属性transform&#xff0c;跟CSS的transform的形变差不多。 HTML transform和SVG transform SVG自带transform属性&#xff0c;例如&#xff1a; <svg width"200" height"150"><rect x"30" y&qu…

5G基站ip如何获取

5G基站的IP地址可以通过以下几种方式获取: 从运营商处获取&#xff0c;即通过联系运营商的客服人员获取。通过网络扫描工具扫描局域网中的IP地址来查找。通过登录管理后台查看网络拓扑结构。通过网络监测和分析软件来获取。 注意: 不同运营商,不同基站的 IP地址都不一样,请确认…

LeetCode No.168. Excel表列名称

class Solution { public:string convertToTitle(int n) {string ans "";while (n > 0) {n - 1; //重点ans.push_back(A (n % 26));n / 26;}reverse(ans.begin(), ans.end());return ans;} };类似问题&#xff1a;171. Excel表列序号 class Solution {int titl…

css中的各种定位

static&#xff1a;静态定位是position的默认值&#xff0c;元素框正常生成&#xff0c;也就是没有定位时的正常显示。 relative&#xff1a;相对定位 用法一&#xff1a;元素相对自身的原位置偏移某个距离&#xff0c;但是原本的空间依旧保留&#xff0c;表现为空白。 用法二&…

druidYAML配置文件打开监控, 给个示例

下面是一个简单的 druid YAML 配置文件示例&#xff0c;用于打开监控&#xff1a; server:type: "simple"host: "0.0.0.0"port: 8082monitoring:druid.emitter:type: "http"host: "localhost"port: 8090druid.monitor:type: "log…

需求入门:原型开发简介

原型开发简介转自&#xff1a;http://www.cnblogs.com/zhoujg/archive/2009/11/15/1603450.html 为什么需要原型 建立原型的主要原因是为了解决在产品开发的早期阶段不确定的问题&#xff0c;利用这些不确定性来判断系统中哪一部分需要建立原型和希望从用户对原型的评价中获得什…