`

编写安全的Symbian C 游戏代码

阅读更多

 

 

本文献给使用Nokia Symbian 60 SDK各个版本开发游戏软件的程序员。虽然本文主要是针对游戏软件,但是大部分内容对一般应用软件也同样适用。

 

1.1.声明

 

为了避免良心的谴责,首先我必须承认一点,我本人并不是靠Symbian C++糊口。除了forum.nokia.com上的文章和SDK,我也没有看过任何关于Symbian的书籍。只是偶然的,我在天津猛犸游戏公司(www.mammothworld.com)认识并接触了Symbian。我从零起步,写出了一个蹩脚的Symbian游戏引擎并在3650、7650上开发了一些游戏。所以我对Symbian的掌握完全是出于自己的猜测和理解,虽然本文缺乏权威,但至少都是经验之谈,容易理解。

 

1.2.概述

 

Symbian游戏是运行在手机上的游戏,它不能干扰手机正常的通讯功能,对操作系统和其它应用程序必须友善。而在首次编写Symbian C++游戏时,我遇到了无数奇怪的问题,其中大部分问题出在内存极端不足,打开太多应用程序,屏幕保护探出,接到短信、电话等特殊情况下。

其实如果养成严谨的代码风格,进行足够的错误处理,大部分问题本可以避免。为了解决它们,我很是花了一番功夫,所以在此把我的一些教训、经验写出,希望大家能避免犯同样的错误。

如果你不是业余爱好者,而是为一个认真的开发商工作,特别是如果你的产品需要通过Symbian Signed认证(www.symbiansigned.com),你就必须更加小心的对待本文提出的问题。

Symbian Signed是一个针对Symbian应用程序的认证,想要通过它,你的应用程序必须通过一系列严格的测试。认证对应用程序的文件管理、内存使用、系统事件响应、网络、资费和私人数据等都有一定的要求。如果想了解Symbian Signed认证的详细内容,可以去它们的网站下载白皮书。

 

1.3.异常处理

 

虽然我们都知道任何一个new (ELeave)或者带有L后缀的函数都可能抛出异常,但是很多业余的爱好者还是会忽视Symbian C++中异常处理的重要性。虽然有些函数只有在极其罕见的情况下才会抛出异常。但不是危言耸听,如果你不写代码捕捉并处理它们,应用程序就会遇到"系统错误"。

普通C++使用throw抛出异常。异常抛出后,栈会不停回滚,直到遇到最近一层catch为止。Symbian C++中的异常处理不使用try-catch和throw。但是它的处理机制和标准C++很是类似,区别仅仅是它只能抛出一个整数错误码,而不是一个任意对象。

我将从异常的抛出、捕捉、处理三方面讲解这部分内容。

 

1.3.1.抛出异常

Symbian C++中,有下面几种情况下会抛出异常:

使用静态函数User::Leave抛出异常。这个函数就是最基本的异常产生函数。下面讲的其它抛出方式都可以转化为User::Leave。

使用静态函数User::LeaveIfError把错误码转化为异常。有些函数比如CFbsBitmap::Create( )有一个TInt的返回值。如果遇到错误,这些函数就会返回非KErrNone的错误值。此时,可以使用LeaveIfError把这个返回值转化为异常。比如:User::LeaveIfError(bmp->Create(iSize, EColor4k); 其实LeaveIfError就是if (returnValue != KErrNone) User::Leave(returnValue);

使用new (ELeave)申请内存。如果没有足够内存可用,此操作产生一个KErrNoMemory异常。比如TText8* p = new (ELeave) TText8[20]; 相当于TText8* p = new TText8[20]; if (p == NULL) User::Leave(KErrNoMemory);

调用带有L后缀的函数。Symbian系统的命名规范中要求,每一个可能Leave的函数都要有后缀L。包含有带L的内层函数调用的外层函数也必须加上L。这类函数中最常见的就是NewL, NewLC和ConstructL。这个规范比你想象的要重要。因为它给其他程序员一个暗示,提示他们对这些函数进行保护。

 

1.3.2.捕捉异常

类似标准C++的catch语句,Symbian C++的TRAP关键字可以对一个可能产生异常的函数进行保护,并且捕获到异常值。比如:

TInt errorCode;

TRAP(errorCode, SomeDangerousFuncL( ) ); // 保护执行SomeDangerousFuncL( )函数

if (errorCode != KErrNone)

{

// 捕捉到了一个异常,在这里添加处理异常的代码

}

类似的TRAPD省去了你声明一个局部变量的麻烦。头两行代码可以简写成:

TRAPD(errorCode,SomeDangerousFuncL( ) );

 

1.3.3.处理异常

对于不同的异常当然有不同的处理方法(废话:-))。我们以最常见的捕获到代表内存不足的KErrNoMemory异常为例讲解。

注意在Container,AppUi等类的构造过程中,你不需要加入对内存不足的保护。因为这一切系统已经为你做好了。系统会弹出一个对话框报告内存不足。根据你的操作系统版本不同,这可能是中文的,也可能是英文或者其它语言的。如果你不信,可以在AppUi或者Container的 ConstructL中写一行User::Leave(KErrNoMemory)试试看。我试验的结果如下:

 

 

除了上面说的特殊情况,你可以简单的弹出一个对话框,告诉用户没有足够的内存运行程序,并且安全的关闭程序。比如我的游戏程序就是这样处理的:

]void CStageManager::DoGameFrame()

{

TRAPD(error, DoGameFrameProtectedL());

if (error == KErrNoMemory)

{

StopGame();

m_noMemoryDlg->ExecuteLD(R_KEY_INVALID_DIALOG);

Exit(); // Call CAknAppUi::RunAppShutter( )

}

else if (error != KErrNone)

{

User::Panic(_L("Some other error."), error);

}

}

其中noMemoryDlg是直接或者间接在Container的ConstructL中创建的:

// in header file

CAknQueryDialog* m_noMemoryDlg;

// somewhere in ConstructL

TBuf<128> errMsg;

_LIT(formater, "Not enough memory. Please close some applications.");

errMsg.Copy(formater);

m_noMemoryDlg = new (ELeave) CAknQueryDialog(errMsg, CAknQueryDialog::EErrorTone);

当然,你也可以制作一个精美的图片来报告内存不足,等待用户按任意键再退出。不过载入这个图片也可能会失败,所以至少在这个图片成功载入之前,你还是需要系统对话框来报告的。

值得一提的是,你不一定需要退出程序,或者你可以稍后重试申请内存,幸运的话,没准第二次就能成功。这是因为Symbian系统会在内存不足时自动关闭一些应用程序。我觉得这是Symbian系统一个比较奇怪的设计。通常应用程序在AppUi的HandleCommandL中会响应EEikCmdExit消息,并且调用CAknAppUi::Exit( )函数(如下代码)。这使得应用程序可以在应用程序管理器中用C键结束掉。这也使得Symbian操作系统有机会在内存不足时通过这个渠道自动关闭一些应用程序。

 

分享到:
评论

相关推荐

    symbian 游戏开发进阶

    - **服务器API**:为了便于开发者编写服务器端代码,Symbian提供了丰富的API接口,涵盖了从网络通信到数据处理等各个方面。 - **安全**:在C/S架构中,安全性尤为重要。Symbian提供了多种机制来保障数据传输的安全...

    Example_game.rar_visual c

    游戏代码通常包括以下几个关键部分: 1. **图形界面**:Symbian S60提供了基本的图形库,如GDI(Graphics Device Interface),开发者需要利用这些库来创建游戏画面,显示方块的移动和旋转,以及消除行的效果。 2....

    基于Symbian OS的手机开发与应用实践(09年度畅销榜NO.7)

    在Symbian OS开发中,C语言通常用于编写底层或资源密集型组件,如驱动程序等。 - **内存管理**:C语言提供了对内存的直接控制能力,开发者可以通过`malloc`和`free`函数手动管理内存。 - **指针操作**:C语言支持...

    S60V2俄罗斯方块C++源代码,适用于6630,7610等手机

    在这个项目中,"src"目录可能包含了游戏的主要逻辑代码,而"inc"目录则存放头文件,定义了类、结构体和其他接口。这些文件是相互关联的,通过包含头文件,一个源文件可以调用另一个源文件中的函数或类。 "编译过程....

    3G手机编程与游戏开发

    理解每种语言的特性和语法是必要的,以编写高效且可维护的代码。 5. **网络编程**:3G网络的使用意味着开发者需要掌握如何通过HTTP/HTTPS、TCP/IP等协议进行网络通信。这包括处理异步请求、错误处理、数据加密和...

    Open Source game engine for Symbian-开源

    这款开源游戏引擎是用C++编程语言编写的,这表明它具有高度的性能和灵活性,因为C++是游戏开发中广泛采用的语言,尤其在需要高效能计算和低级别内存管理的场景中。 "inc"目录通常包含所有头文件(.h或.hpp),这些...

    JAVA手机游戏开发PPT教案学习.pptx

    程序员的角色是编写代码将这些创意变为现实,他们通常使用Java或其他编程语言。测试人员则对游戏进行详尽的测试,确保其稳定性和可玩性。最后,市场运营团队负责推广和销售游戏。 Java作为一种流行的编程语言,尤其...

    超过10种大型程式的案例

    在LED屏幕控制中,开发者通常需要编写驱动程序来与硬件通信,这可能包括串行通信协议(如SPI或I2C)以及理解RGB或像素阵列的控制逻辑。同时,对于实时性要求高的应用,需要了解如何优化代码以确保流畅显示。 2. **...

    Android开发技术的搜集积累

    虽然Android底层使用C/C++编写,但大多数应用程序层代码都是用Java编写的。此外,近年来Kotlin也被广泛应用于Android应用开发中。 - **开发工具**:Android Studio是官方推荐的集成开发环境(IDE)。它基于IntelliJ ...

    lua脚本基础

    Lua可以用于编写辅助工具,如数据格式转换,通过调用C语言导出的函数来实现更复杂的任务。 3. **动态配置**: 在移动设备或嵌入式设备上,Lua用于动态配置,可以远程下载脚本来适应不同的设备参数。 **安装与...

    C++高级软件工程师

    - **3D游戏开发**:了解3D游戏引擎的基本架构,学习OpenGL等图形库的使用。 #### 六、软件工程与项目管理 - **敏捷开发**:了解敏捷开发的理念和Scrum框架。 - **需求分析**:学习如何有效地收集和整理用户需求。 -...

    2019年嵌入式应用实践总结.pdf

    学习C语言不仅需要理论知识,更重要的是实践操作,通过编写代码来加深理解和解决问题。 此外,了解操作系统原理是嵌入式开发的关键,如进程、线程管理,资源分配等。这有助于理解硬件与软件之间的交互。对于Linux或...

    基于智能手机android操作系统图片浏览器设计.doc

    这一底层主要由C语言编写,负责处理硬件驱动、内存管理、进程调度等基础功能。中间层则包含库函数和虚拟机,这些是通过C++开发的,它们为开发者提供了丰富的API接口,如OpenGL ES用于图形处理,SQLite用于数据库管理...

    Qt+Quick+for+Mobile

    开发者可以使用 Qt Quick 创建复杂的用户界面,只需要描述 UI 的结构和样式,而不需要编写大量的代码。 Qt Mobile UI Offering Qt Quick 提供了一个完整的移动应用程序开发解决方案,包括了开发、测试、调试和发布...

    嵌入式手机

    开发人员使用集成开发环境(IDE)如Eclipse、Xcode或Android Studio来编写代码,并使用模拟器或物理设备进行测试。此外,还需要熟悉嵌入式编程语言,如C/C++、Java或Swift,以及相关的调试工具和技术。 在现代通信...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    Android 一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导开发 IOS 由苹果公司开发的移动操作系统 Webkit 一个开源的浏览器引擎,在手机上的...

Global site tag (gtag.js) - Google Analytics