原创 我喜欢Symbian收藏

新一篇: Symbian 智能指针 | 旧一篇: 简单但还比较实用的模板技术

Symbian 是Nokia,爱立信等高端PDA手机中常用的一个操作系统, 原生的SDK是C++, 所有的API都是直接使用C++语法, 当然为了兼容的原因, 仍然提供了标准C library, 不过功能并不完善, 在symbian中也不推荐使用, 不过我觉得用也无妨,, 因为C的接口比较简单.

Symbian是一个比较陈旧的操作系统, 使用C++开发的时间大概在90年代早期, 基本上没有用到什么高深的C++特性, 例如STL等, 当时C++编译器也没有现在这么高级. 现在看, 我个人认为Symbian是一款较差的融合了C/C++/Java等各种语言的缺点,( 当然当时还没有Java), 而组合成的一个预计在未来不超过10年的时间需要被进行大幅度整改的基于C++的操作系统, 其中它对C++语义的无情摧残和丑陋的Leave机制, 基本上使得在Symbian上开发C++完全就像在走钢丝, 使得C++语言中提供的一个及其重要的特性"确定性析构" 无法在Symbian上得到保证.

没有确定性析构, 就没有RAII, Symbian中没有异常, 因此就使用了一种类似C中longjmp的机制, 由于longjmp并不自动进行stack unwind, 因此Symbian提供了Cleanup Stack, 要求程序员手工将执行析构动作的函数指针填入一个Stack列表中, 当longjmp(leave)的时候, 会一一调用在这个Stack中的函数, 以释放资源.

基本上来说, 对比现在的C++异常, Leave机制基本上没有提供任何比C++异常好的地方, 无论是效率还是内存消耗, 而且Leave机制具有错误倾向. 毕竟这些事情人还是不如编译器.

Symbian为了满足它的Leave机制, 提供了几个T,C,R,M class类别.

C class:
   所有原本具有non-trivial构造函数的class按照Symbian的定义, 都应该是一个C class. 需要采用两阶段构造, 先new一块内存, 然后在构造函数中不能再进行任何内存分配等任何可能引发Leave的函数, 也就是保证ctor必须成功, 然后在提供另外一个函数在进行必要的初始化, 这个在Symbian中一般命名为ConstructL. 为了避免程序员不小心漏过ConstructL, 因此一般这个构造函数都不是public, 而提供一个静态的NewL或者NewLC静态工厂函数返回新创建的对象的指针. 如下:
   class CFoo
   {
   public:
     static CFoo* NewL();
     ~CFoo();
   protected:
     CFoo();
     void ConstructL();
   };

得到这个指针以后, 为了实现Leave完全( symbian SDK中的不少函数内部都是Leave的) , 因此必须对这个裸指针进行保护. auto_ptr? 别做梦了, 前面说来Leave机制发生的时候没有确定性析构. 因此需要将这个对象手动插入到Stack中,  见#1

  CFoo * foo = CFoo::NewL();
  CleanupStack::PushL(foo);         #1
 
  do_sth(..);
 
  CleanupStack::PopAndDestroy(1);   #2

还要写一个#2, 调用foo的析构函数.

而由于PushL需要调用Foo的析构函数, 因此这个Foo应该继承自一个基类, 以使得析构函数为virtual. Symbian提供了一个class用于被所有的C class继承, 即CBase. 因此我们的CFoo 就应该从CBase继承.

 对比有C++ Exception的实现, 程序员可以:
 CFoo foo;
 do_sth(..);

对比上面使用Leave机制的例子, 哪个好一目了然.

由于C class的特性, 决定了Symbian中很难使用多重实现继承, 这个并不是太大问题. 但是要求所有的C Class都必须分配在Heap中, 就有点类似"纯OO"Java的味道了, 但是又没有GC可用, 因此大量的登记工作就全留给程序员了. 而且从Heap中分配和从Stack中分配速度相差不少.

又如果你一个大的C class包含有2个其他的C class作为成员变量, 对了, 那也是你最爽的一种.
这两个C class对象也必须使用New的方式创建出来. 也就是C++中的Pimpl手法.

R class 同样, 还是类似 "纯OO"的Java, 提供一个Close()函数释放资源, 基本上都是C++中最难用的方法.


还有一点就是Symbian中的DLL不能有data段, 也就是没有静态数据. 没有静态数据连个singleton都实现不了, 更别提其他的用处了.Symbian的大概解释是: 一个DLL如果有静态数据, 那么对于每个调用了这个DLL的Process都需要分配一个内存块, 最小的单位是4K. 因此如果一个DLL被N个进程使用, 那么即使只有一个字节的静态数据, 浪费的大小也是 N * 4K, 因此不可接受.

明智之举!!

我写的DLL从来就是我自己公司的一个破烂程序使用, 别人根本就不调用我的DLL, 因此根本没有N个进程, 因此也就浪费4K. 而且我程序越大, 需要的静态数据就越大, 因此4K最小分配单位根本就不是一个问题.

系统的DLL可是被很多进程调用的啊? 这个开销可不少啊. 对啊, 但是系统的DLL又不是我写的, 是你们这些绝顶聪明之人所为, 你可以不用啊. 为什么要限制我们使用了?

还有一本中文版的Symbian的书好像说到一点: Symbian的这些genius为了防止我们这些傻瓜们滥用静态数据,  因此干脆就去除了这个特性.

这个解释我最喜欢, 也觉得最合理, 符合C/C++的传统精神: 程序员都是傻瓜.

我喜欢Symbian!!

发表于 @ 2005年07月12日 11:15:00|评论(loading...)|编辑

新一篇: Symbian 智能指针 | 旧一篇: 简单但还比较实用的模板技术

评论

#chenziteng(陈子腾) 发表于2005-07-24 12:02:00  IP: 61.186.252.*
1. Symbian手机按界面风格大致可以分为三种:
Series 60, 智能手机(smartphone),如Nokia 6600
UIQ PDA手机,如Sony Ericsson P900
Series 80, 通讯器(communicator),如Nokia 9300
其中智能手机占市场份额最大,因此更应该统称为“智能手机”而非“高端PDA手机”

2. 如你所言,Symbian提供的C语言标准库并不完善,真正使用的时候可能遇到诸多问题,所以不推荐。当然如果你用的功能相当基本,不会遇

到那些问题,则“用也无妨”

3. 我不知道你评判新与旧的标准是什么,看看这份年表:
1981, DOS 1.0
1985, Windows1.0
1990, SIBO(EPOC16)
1994, Linux 1.0
1996, Palm OS 1.0
1996, Windows CE 1.0
1997, EPOC32(Symbian OS 1.0)
从这个表上看,现在所说的Symbian OS比同类OS出现得晚,不能算是tooold吧。

4. 十年太长了,不知道那个时候Symbian是否还活着,你知道,微软老大对竞争对手向来心狠手辣......

5. 据Symbian自己解释,不使用异常机制原因是:
(1) Compiler support for C++ exception handling was unavailable or inadequate at the time Symbian OS was designed.
(2) Symbian OS exception handling is specialized for use with other Symbian OS conventions (C and T classes, 32-bit integer

error codes), allowing lower overheads than for C++ exception support.

6. 同意手动不如自动,太累了。因此更盼着你把auto_ptr完善完善发给大家用,哈哈。

7. 对于WSD(Writable Static Data),这的确很不方便,特别对于做代码移植来说。不过这是受手机内存资源限制的结果,有历史原因。单单

看那一段话太笼统了,还是多看些资料再做评判吧,参见:
Why doesn't Symbian OS support writeable static data
http://www3.symbian.com/faq.nsf/45aef46f9a8a61f9802569de0067eb63/71c212db06dce71380256d6e005ad2a8?OpenDocument

当然随着时间的发展,Symbian在逐步放开限制,比如EKA2内核就开始支持WSD了,参见:
Does Symbian OS provide support for writeable static data (WSD)?
http://www3.symbian.com/faq.nsf/0/0840F25CB
#ilovevc 发表于2005-07-25 11:22:00  IP: 61.186.252.*
你给的链结我怎么都打不开?
5, 7, 8 我都可以举出一些反例. 例如5 就要求所有类从CBase派生, 这是要runtime开销的, 至少要vptr吧? 另外建立vtable要代码段开销的, 又, 所有的Cbase对象必须从heap中创建这个也是要开销的等等.

7, 8 我估计我都看过这些文章了, 都是狡辩和欺骗. 就是我上面说的, 无非是一个DLL至少要4K, N个进程就每个进程都要4K. N个进程连接N个DLL又如何等等这些数字游戏. 我文中都提到了这些根本不成立.
#chenziteng(陈子腾) 发表于2005-07-26 22:58:00  IP: 61.186.252.*
  我打得开,你打不开,我们管这叫RPWT,哈哈。

  先别那么愤,谁也没跟你争,哈哈,只不过有人FYI过来这篇贴子的链接,我就大致浏了一遍。

  其实早就见过一个哥哥,下得工夫比你还大,砖拍得比你还狠,有心情就看看:

Symbian OS design faults
By Hrissan
http://www.codeproject.com/useritems/Symbian_OS_design_faults.asp

  反正现在不管什么东西网上都是夸的有骂的也有,见多了就麻木了。

  我还是那句话:该干嘛干嘛去吧。
#ilovevc 发表于2005-07-27 08:58:00  IP: 61.186.252.*
blog不就是发牢骚的地方吗? 呵呵
写这个主要还不是郁闷, 而是感觉Symbian有点愚民.
#mythma 发表于2005-10-26 09:58:00  IP: 211.100.21.*
Symbian有点愚民, 那就炒他鱿鱼,哈哈.
#ilovevc 发表于2005-10-26 22:15:00  IP: 211.100.21.*
最近已经解脱了, 不再开发symbian了。哈哈
发表评论  


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