S60编码诀窍.pdf

### S60编码诀窍——Symbian OS内存管理与编码实践####一、简介在《S60编码诀窍.pdf》中,文档着重介绍了Symbian OS平台下C++编程的一些关键技术和最佳实践,特别是针对内存管理和防止内存泄漏的方法。这部分内容对于所有使用C++为Symbian OS 6.x/7.0s开发应用程序的开发者来说至关重要。 ####二、内存管理##### 2.1清除堆栈(CleanupStack) **2.1.1所有程序都应检查“资源用尽”出错**在Symbian OS中,开发者必须确保他们的应用程序能够优雅地处理资源耗尽的情况。例如,当内存不足时,操作系统会抛出`EOutofMemory`异常。因此,所有程序都应当在适当的位置添加错误检查,以确保即使在资源紧张的情况下也能正常运行。例如: ```cpp User::LeaveIfError(aStatus); ```这里`aStatus`是从一个可能会抛出异常的函数返回的状态值。 **2.1.2传统的侦错方法**传统的侦错方法通常涉及在代码中放置多个`if`语句来检查错误状态,并且在检测到错误时释放资源。这种方法虽然直观,但在大型项目中维护起来非常困难,尤其是在需要处理大量资源的情况下。 **2.1.3使用传统方法的问题**传统的错误处理方法存在几个主要问题: 1. **代码冗余**:每个资源都需要显式释放,导致重复代码。 2. **易出错**:手动管理资源容易遗漏,尤其是在异常路径上。 3. **可读性和可维护性差**:过多的错误处理代码会干扰核心逻辑。 **2.1.4 Symbian OS中的解决方案** Symbian OS提供了一种更为高效和安全的方式来处理这些问题:通过使用清除堆栈(`CleanupStack`)和异常处理机制。这种方法可以自动清理资源,无需在每条路径上手动释放资源。 ##### 2.2规则1:异常退出函数和捕获模块**2.2.1异常退出函数** Symbian OS提供了异常退出函数`User::Leave()`和`User::Panic()`,用于在发生错误时优雅地结束函数执行。这些函数会抛出一个异常,同时触发清除堆栈。 **2.2.2 `new(ELeave)`运算符**为了更好地控制资源分配,Symbian OS引入了`new(ELeave)`运算符。当使用这个运算符分配内存时,如果内存分配失败,则会立即抛出`ELeave`异常,从而触发清除堆栈。 **2.2.3 `NewL()`和`NewLC()`惯例** - **`NewL()`**:这个宏用于创建一个对象,并且隐含地调用了`User::Leave()`。这意味着如果对象创建失败,则会抛出异常并触发清除堆栈。 - **`NewLC()`**:类似于`NewL()`,但还包含了清除堆栈的逻辑。当对象不再需要时,应调用对应的`DeleteMe()`方法来释放资源。 **2.2.4 `TRAP`和`TRAPD`使用捕获模块** `TRAP`和`TRAPD`是Symbian OS中用于异常处理的两个宏。它们可以在捕获块中捕获异常,并允许开发者指定异常处理逻辑。例如: ```cpp TRAPD(Err, SomeFunction()); //如果SomeFunction()抛出了异常,Err将包含错误码``` ##### 2.3规则2:使用清除堆栈**2.3.1为何需要清除堆栈**清除堆栈是一种内置的机制,用于在发生异常时自动清理已分配的资源。这有助于防止内存泄漏,并确保程序的稳定性。 **2.3.2使用清除堆栈**开发者可以通过以下方式使用清除堆栈: 1. **自动清理**:当异常被抛出时,清除堆栈会自动清理所有分配的资源。 2. **手动管理**:还可以通过调用`CleanupStack::PushL()`和`CleanupStack::Pop()`来手动管理资源。 ##### 2.4规则3:两阶段构造**2.4.1用`NewL()`和`NewLC()`实现两阶段构建** Symbian OS推荐使用两阶段构造模式来确保资源的安全分配和释放。第一阶段使用`NewL()`或`NewLC()`创建对象;第二阶段完成对象初始化。如果初始化失败,可以安全地释放资源。例如: ```cpp class MyClass { public: TPtrC* iText; MyClass(TPtrC& aText) { iText = NewL(aText); } void ConstructL(TPtrC& aText) { iText = NewL(aText); //初始化其他成员User::LeaveIfError(someFunction()); //成功时调用FinishConstructionL() FinishConstructionL(); } void FinishConstructionL() { //完成对象初始化} ~MyClass() { CleanupStack::PopAndDestroy(iText); } }; ```在这个例子中,`ConstructL()`和`FinishConstructionL()`一起构成了两阶段构造模式。 ##### 2.5公共错误**2.5.1误用`TRAP`和`TRAPD`**开发者有时会错误地使用`TRAP`和`TRAPD`宏。正确的做法是在捕获块中处理异常,并且确保所有的资源都被适当地清理。 **2.5.2错误使用了`new`运算符**直接使用`new`运算符而不是`new(ELeave)`可能会导致程序在内存不足时崩溃,而不是抛出异常。 **2.5.3错误使用了后缀`'L'`**在Symbian OS中,`'L'`后缀通常表示一个函数或宏会在异常情况下抛出异常。错误地使用或忽略了这个后缀可能导致代码不符合预期。 ##### 2.6内存泄漏**2.6.1使用WINS模拟器中的工具** Symbian OS提供了一系列工具,如WINS模拟器中的内存分析工具,可以帮助开发者识别和修复内存泄漏问题。这些工具可以在开发过程中早期发现潜在问题。 ####三、系统资源的使用(ROM和RAM) ##### 3.1重要性在移动设备上,尤其是Symbian OS平台上,ROM和RAM资源是非常宝贵的。合理地管理和使用这些资源对于提高应用性能和用户体验至关重要。 ##### 3.2减少代码量**3.2.1不必要的导出函数**导出未使用的函数会增加ROM大小,应该避免这种做法。 **3.2.2复制和粘贴**过度使用复制和粘贴会导致代码重复,增加ROM大小,而且难以维护。 **3.2.3明显不可分解的函数**将功能相关的代码组织在一起可以减少代码大小,并提高可读性和可维护性。 **3.2.4过分的`TRAP`模块**过度使用`TRAP`模块会增加代码体积,应该尽量减少其使用。 **3.2.5调试发行代码**发行版代码不应该包含调试信息,这可以显著减小ROM大小。 **3.2.6不必要的虚函数**过度使用虚函数会导致额外的虚函数表开销,增加ROM大小。 **3.2.7使用公共控件**使用经过优化的公共控件库可以减少代码体积,并提高开发效率。 ##### 3.3减少使用RAM **3.3.1使用bitfields(位元组合),而不使用太多的`Tbools`**使用位字段(`bitfields`)代替布尔类型可以节省内存空间。 **3.3.2阵列粒度的使用警示**避免创建过大的数组,因为它们会占用大量的RAM。 **3.3.3避免全局数据**全局变量会持续占据RAM空间,应该尽量减少使用。 **3.3.4小心基类的成员数据**基类中的成员数据可能会无意中增加派生类的RAM使用。 **3.3.5正确使用清除堆栈**确保清除堆栈正常工作,可以有效地回收不再需要的资源。 **3.3.6尽早删除**一旦不再需要对象,就应该尽快释放它们,以释放RAM。 **3.3.7用最大数据集进行硬件测试**在测试阶段使用最大的数据集可以确保程序在最坏情况下的性能。 **3.3.8分解复杂的长运算**将复杂的长运算分解为更小的部分,可以减少临时变量的数量,从而减少RAM使用。 ####四、总结Symbian OS为C++开发者提供了一套强大的工具和技术,帮助他们编写高质量、高效的代码。通过遵循文档中的指导原则,开发者可以有效地管理内存资源,防止内存泄漏,减少ROM和RAM的使用,从而提高应用的整体性能和可靠性。这些实践不仅适用于Symbian OS,许多原则也可以应用于其他嵌入式系统和移动平台。
pdf 文件大小:379.76KB