Categories: Lang-CN | Symbian C++ | Symbian OS | S60 | Debugging | Essential Idioms | Base/System | Code Examples
This page was last modified 09:40, 26 June 2008.
内存管理
From Forum Nokia Wiki
内存管理
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而不是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);
清除栈
使用清除栈
- 把条目(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’。
两阶段构造
NewL()和NewLC()
这两个静态函数一气呵成执行两个构造阶段。提供New()或NewLC()为类的一部分使得这个类用起来更容易。NewLC()被典型用在某个函数含有一系列的自动变量(指向堆内存),省得将每一个推入清除栈。
内部链接
| Related Discussions | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| 链接-----Symbian中文技术周刊 | beover1984 | Symbian | 0 | 2006-08-23 07:49 |
| 请问堆描述符用完后要delete或pop么? | luckyapplehead | Symbian | 7 | 2008-02-20 10:31 |
| 怎么在设备上调试程序呢? | awfulsoul | Symbian | 2 | 2006-10-10 04:06 |
| Symbian中文技术周刊第一期(内存管理&设备调试专题) | WJsharp | Symbian | 27 | 2006-08-27 04:13 |
