×
Namespaces

Variants
Actions

内存管理

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

文章
dougcn 在 26 Jun 2008 创建
最后由 hamishwillee 在 30 May 2013 编辑

内存管理

Contents

内存管理

Symbian OS的一个基本特征是为具有有限内存容量和可用资源的设备而设计的。因此,它需要非常有效的内存管理。由于缺少资源,任何应用都有可能发生运行时错误: 比如,机器内存用完了或者访问硬件资源失败。这些错误被认为是异常(Exception),不可能通过修改程序阻止它们的发生。所以,程序应当能够在异常发生时恢复。

这样,对于Symbian OS来说,好的内存管理的关键需求如下:

  • 有效编程,你的程序未使用不必要的内存
  • 尽可能早释放资源(记住资源是有限的)
  • 处理内存不够(out-of-memory)错误,事实上你需要对应有内存分配的每一个操作。
  • 当操作中内存不够发生时,返回可接受的稳定的状态,确信你清理了那个操作中分配的一切资源。

内存管理模块

  • 栈和堆
  • 异出(Leave)
  • 清除栈
  • 两阶段构造
  • 内存泄漏
  • Panics
  • 调试

栈和堆

在栈上:

  • 对象被自动删除
  • 缺省大小是 8Kb

在堆上:

  • 对象必须由程序员使用delete删除
  • 大小取决于设备,但一般 > 0.5Mb

例子:

TInt i = 0;
CMyObj* obj = new (ELeave) CMyObj;

这里,i存储在栈上,而obj指向堆内存。

对象在栈上声明时,对象离开其作用范围时被自动删除。缺省的栈大小是8Kb,但可以在项目中(.mmp文件)用epocstacksize声明增大这个值。项目文件中的使用会被后续模块覆盖掉。(注: 使用Emulator时,变更栈大小不起作用。)

作为对照,对象在堆上自动分配时,它需要由程序员使用delete关键字明确删除。若未删除,则发生内存泄漏。在给定设备上,堆的大小会随着可用内存而变化,但应超过0.5Mb。

异出(Leaves)

Leaves

  • 使用Leaves而不是C++ exceptions
  • 当有资源失败时,代码异出”Leaves”
  • 向上传播调用栈知道被处理
  • 概念上,异出(Leaves)等同于抛出一个异常(exception)
  • 如没有足够内存可用,new操作符已被重载以便异出(Leave)
  • 使用 new (ELeave)
  • 正常使用delete释放内存
  • 可能异出(Leave)的函数应以"L"结尾

异出(Leave)例子

  • 动态内存分配:
return new (ELeave) TUint8[100];
  • 引发异出(Leave)
User::Leave(KErrNotFound); // from e32std.h
  • 若无内存则异出(Leaving)
User::LeaveNoMemory();
  • 若为NULL则异出(Leaving)
void CMyClass::SetCallbackL(MNotify* aNotify)
{
User::LeaveIfNull(aNotify);
...
  • 若错误发生则异出(Leaving)
RFs fileServer; // handle to file server
TInt error = fileServer.Connect();
User::LeaveIfError(error);

清除栈

清除栈 非CBase类的清除栈支持

使用清除栈

  • 把条目(items)放到清除栈,用
CleanupStack::PushL(ptr) 用于指针——在异出事件中所指内存将被删除。
 
CleanupClosePushL(handle) 用于句柄——在异出事件中句柄将被关闭。
  • 把条目(items)从清除栈删除,用
CleanupStack::Pop(pointer) 移除顶部条目
 
CleanupStack::PopAndDestroy(pointer) 移除并删除/关闭条目
  • 将对象推入清除栈,当

• 对象被一个本地指针引用,且仅当 • 在该对象生命周期内调用了一个会异出(Leave)的函数

  • 不要把类成员变量推入清除栈

例子:

这里,若ConstructL()异出,self将被自动删除:

CMyClass* CMyClass::NewL(TInt aBufSize)
{
CMyClass* self = new (ELeave) CMyClass;
CleanupStack::PushL(self);
self->ConstructL(aBufSize);
CleanupStack::Pop(self);
return self;
}
  • 当异出不再可能发生时,压入的条目应该从清除栈中弹出
  • 若函数需要在退出前把对象留在清除栈中,则函数名末尾必须有个‘C’。

两阶段构造

Two-phase construction

NewL()和NewLC()

这两个静态函数一气呵成执行两个构造阶段。提供New()或NewLC()为类的一部分使得这个类用起来更容易。NewLC()被典型用在某个函数含有一系列的自动变量(指向堆内存),省得将每一个推入清除栈。

内部链接

This page was last modified on 30 May 2013, at 07:37.
62 page views in the last 30 days.