“BREW拼盘”大奉送!——调试技巧搭配典型错误解决

技术与开发

上期我们介绍了“Hello World”编程,大家已经学会了吧。私下用自己编写的代码进行调试时,是不是发现上期使用的调试方法太简单?碰到各种错误却又不知道如何解决?这期我们就来讲讲BREW程序的基本调试方法和调试过程中常见的错误。

一、调试代码

1.在BREW模拟器下调试

启动BREW模拟器后,选择“View→Output Window” 菜单命令,在输出窗口里面显示模拟器上程序运行的信息,包括按键响应、后台消息等。我们还可以在代码中使用语句输出带文字的调试信息,来观察代码的运行,及时提示错误信息。这里以“Hello World”为例,具体代码如下所示:

static boolean firstapp_HandleEvent(firstapp* pMe, AEEEvent eCode, uint16 wParam, uint32 dwParam)

{

AECHAR szText[] = {'H','e','l','l','o',' ','W','o', 'r', 'l', 'd', '\0'};

switch (eCode){

case EVT_APP_START:

//输出文字到调试窗口

DBGPRINTF("Run IDISPLAY_DrawText");

IDISPLAY_DrawText(pMe->a.m_pIDisplay,

AEE_FONT_BOLD,

szText,

-1,

0,

0,

NULL,

IDF_ALIGN_CENTER | IDF_ALIGN_MIDDLE);

//输出文字到调试窗口

DBGPRINTF("Run IDISPLAY_Update");

IDISPLAY_Update (pMe->a.m_pIDisplay);

运行效果如图1所示。

30-f15f16-2.jpg
图1

小提示:使用“DBGPRINTF”函数时需要在程序里包含头文件“AEEStdLib.h”。

2.在VC下调试

用VC进行调试,方法如下:

第一步:设置断点

首先把光标移动到需要设置断点的代码行上,然后按快捷键F9 可以在该行设置断点。断点处会显示一红色圆点。

第二步:调试运行

按快捷键F5进入调试运行状态,当程序遇到异常错误停下来时,会自动跳到出错的代码处,方便我们检查问题。

第三步:单步执行

程序在遇到断点停下后,可以使用快捷键F10/F11逐句向下执行,区别是按快捷键F10遇到函数时不进入子函数内部,而按快捷键F11会进入子函数内部。同时,我们还可以通过VC下方的Watch窗口观察程序运行过程中各个变量的值(图2)。

30-f15f16-3.jpg
图2

二、程序错误解决方案

问题1:模拟器上找不到程序图标

辛辛苦苦写好了代码,编译又通过了,但是启动模拟器,却怎么也找不到我们的小程序图标,只有系统自带的。这个原因就是MIF文件的路径不对了。

在模拟器上选择“Tools →Settings”,看到“Initial MIF Directory”栏里显示的目录是“C:\Program Files\BREW 3.1.5\sdk\examples”,这个就是模拟器选择运行应用程序的目录,定位到该目录,可以找到一些MIF文件。

所有在模拟器上出现小图标的程序,这里都有相应的MIF文件,我们只要把“firstapp.mif”复制到“examples”目录下,再次启动模拟器,就能看到我们的小程序图标了。

问题2:启动程序时模拟器上出现:“This application has been unloaded to save memory. You must download a new version.”

和问题1类似,这个提示信息是指找不到可运行的DLL文件。在模拟器运行目录下,确保“firstapp.mif”和工程文件夹“firstapp”并列,并且保证“firstapp.dll”在“firstapp”文件夹里(图3)。

30-f15f16-4.jpg
图3

问题3:出现“Unknown Error”错误提示(图4)

30-f15f16-5.jpg
图4

这是由于Class ID不匹配造成的,检查一下BID文件和MIF文件里的ID是否一致,如果不一样,就可能出现这种问题。

问题4:程序运行正常,退出时屏幕提示“Module failed to free all memory”

该提示的意思是应用程序在退出之前没有能释放掉所有程序运行期间分配的内存,造成内存泄漏。由于在BREW设备上的可用内存是有限的,因此清理不使用的内存就十分重要了。推荐在内存不再使用的时候就释放掉。

假设我们使用了“IMenuCtl”接口,退出时这样释放就没有问题了:

// if ( pMe->pIMenuCtl != NULL ) // 判断对象是否为NULL

// {

// IMENUCTL_Release(pMe->pIMenuCtl) // 释放对象

// pMe->pIMenuCtl = NULL; // 设置对象为NULL

// }