·天新网首页·加入收藏·设为首页·网站导航
数码笔记本手机摄像机相机MP3MP4GPS
硬件台式机网络服务器主板CPU硬盘显卡
办公投影打印传真
家电电视影院空调
游戏网游单机动漫
汽车新车购车试驾
下载驱动源码
学院开发设计
考试公务员高考考研
业界互联网通信探索
Symbian内存管理
http://www.21tx.com 2009年11月25日 天极网

  Why Memory Management

  Symbian OS本身就是为内存和资源受限的设备开发的,应用程序运行过程中很可能碰到内存用光,或者硬件资源不可用的情况。而这种exceptions是通过修改程序无法解决的,所以遵守以下几条:

  尽量不要使用不必要的RAM

  尽早释放资源,如文件server等

  当你每次申请内存时,都须准备处理out-of-memory错误

  当 out-of-memory错误发生时,返回到一个stable的状态,并释放所有期间申请到的资源

  Stack and Heap

  Stack:默认大小8kb,自动删除,如 TInt i = 0;

  Heap :至少0.5Mb,由程序员手动删除,如 CMyObj* obj = new (ELeave) CMyObj;

  Leaves

  首先介绍Conventional C++ Memory Management,在Symbian看来,这是非常低效率的。

  NULL Pointer Checking if ((myObj = new CMyObj( ) ) == NULL) { //Error Handling }

  ANSI C++ Exeption Handling try { //throw an Exception } catch (int e) { //Error Handling }

  在Symbian中推荐采用Leave,如果内存或者资源不能分配到,这个代码就会Leave,沿着Call Stack,直到操作系统或者在某个函数中被Handle掉。

  所有可能Leave的函数最好以L结尾,保证该函数的用户知道这个函数可能Leave。

  Leave的例子:

  动态内存分配: return new (ELeave) TUint8[1000];

  产生一个Leave:User::Leave(KErrNotFound);

  内存不足时Leave:User::LeaveNoMemory();

  NULL的时候Leave:User::LeaveIfNull(aNotify);

  当发生错误时Leave:RFs fs; TInt err = fs.Connect(); User::LeaveIfError(err);

  处理Leave:

  操作系统有默认的处理Leave的方式:

  在程序启动过程中:直接关闭应用程序。

  应用程序启动后:显示一个错误消息。

  开发者可以通过trap装置来处理Leave。TRAP(_r, _s)和TRAPD(_r, _s),其中:

  _r:是一个TInt类型的leave code,默认值为TErrNone。

  _s:一系列可能Leave的C++ Statements。

  TRAPD(err, DoFunctionL());

  if (err != KErrNone)

  { //Error Handling }

  else

  { //Everything is well }

  The Cleanup Stack

  cleanup stack用于存储在leave发生后需要deallocating的局部变量(指针)。即:当一个函数leave了,所有在cleanup stack上的对象会被全部删除掉。

  Cleanup Stack的使用方法:

  CleanupStack::PushL(ptr) :当发生leave时所有内存都会被释放

  CleanupClosePushL(handle):当发生leave时这个句柄(handler)会被关闭

  CleanupStack::Pop(pointer):第一个元素出栈

  CleanupStack::PopAndDestroy(pointer):第一个元素出栈并释放内存

  如果一个函数可能leave,检查一下两种情况:

  如果leave了,是否所有在堆(heap)上的元素都在cleanup stack中了

  如果没有leave,你是否自己恰当地将他cleanup了

  CMyClass* CMyClass::NewL(TInt aBufSize)

  {

  CMyClass* self = new (ELeave) CMyClass;

  CleanupStack::PushL(self);

  self->ConstructL(aBufSize);

  CleanupStack::Pop(self);

  return self;

  }

  如果某个函数会在cleanup stack上留下一个对象,那么他必须以C结尾。

  Two Phase Construction

  C++构造函数一定不能leave。所有内存和资源的分配应该在第二阶段构造函数ConstructL( )中完成。

  编码指南,所有用户定义的C类必须:

  定义NewL和NewLC函数为public static

  定义ConstructL和C++ Constructor为private

  Best Practise

  Construction的规则:

  默认的C++构造函数中不能含有可能leave的代码

  可能发生leave的函数必须在ConstructL中被调用

  如果基类也有ConstructL,必须首先调用,不要忘了explicit scoping

  Destruction的规则:

  C类必须在析构函数中删除它自己所包含的对象

  在删除一个对象后,把它的指针设为NULL

  不要删除不是本类所拥有的对象

  在reallocation前首先删除对象,并且将其指针设为NULL

  Further Discussion:

  Preserve Stack Memory:每个进程只有8K,以引用的方式传递参数,大的对象放在堆上

  Preallocation vs last moment allocation:一般的原则是只在使用前分配资源并且在使用后马上释放。但是 preallocation的好处是节约处理时间,并且在没有内存的情况下照常运行(资源已经分配到了)

  where to put trap harness:最基本的情况是依靠GUI应用程序的框架。根据应用的不同,可以自定义粒度。

  Error Code Returns vs. leaving functions:在执行某个处理前检测是否会出现问题,如下代码:

  User::LeaveIfError(fs.Connect());

  Memory Leaks

  如果你的程序有内存泄露,在模拟器上关闭时会crash。尽早发现并解决你的内存泄露,因为你可以追查到你可能导致内存泄露的代码改动。如果实在找不到,可用下面方法:

  Heap Balance Checking:

  _UHEAP_MARK

  _UHEAP_MARKEND

  用上述这两个宏放在你要检查的代码的开头和结尾,如果发生panic,则说明这段代码中发生了内存泄露。可以嵌套使用。

  Panics

  Panic是一个未经处理的exception,暗示着一个无法解决的错误。

  一般程序有以下三类错误:

  程序错误:如引用一个超过数组范围的元素

  环境错误:内存、磁盘空间不够,或缺少其他资源等

  用户错误:输入错误数据

  可以使用trap和cleanup stack技术来解决环境和用户错误,但是对于第一类的程序错误,我们无法恢复,最好是使用User::Panic()函数,它带有两个参数,第一个是string,第二个是Tint。

上一篇: Symbian C++ 各种类型之间的转换
下一篇: 三星:我们不会放弃塞班和其它平台技术

关于我们 | 联系我们 | 加入我们 | 广告服务 | 投诉意见 | 网站导航
Copyright © 2000-2011 21tx.com, All Rights Reserved.
晨新科技 版权所有 Created by TXSite.net