Symbian程序开发有其特殊性,不但表现在其特有的语言层面的实现机制--例如Descriptor, 而且在调试方法上也有很大不同。本文就此做一些概念上的说明性介绍,很多方法的引入(尤其是建设性的方法)是来自于Peter Jiang的文献。当然他的一些思想也是有根源的,这些都在最后的参考列表中给出来。我充其量来说,是归纳总结和呈献者。
本文的一些介绍是基于这样的开发环境:Microsoft Visual Studio 2003.net + S60 SDK + Carbide.vs。 一些调试方法确实依赖于开发环境,比如使用IDE调试器。我没有使用除此之外的开发环境,因此结合你自己的开发环境来看,可能会和下面的方式有所不同。
1.使用Visual Studio 调试器进行调试及存在的问题
一种常见的方法是在自认为存在问题的代码处设置断点,然后让IDE在"调试模式"下运行模拟器。当应用程序运行时,执行流会暂定在断点处。源代码将显示在IDE中,并且同时显示与应用程序相关的所有符号调试信息。接着可以使用IDE的调试特性单步调试代码片断。你可以查看IDE显示的应用程序源代码、数据、调用堆栈和其它与调试相关的信息,帮助自己跟踪到代码或逻辑中的错误。这种方法不值得多介绍,因为它根本不是什么新方法。
但是在我们自认为IDE调试器使用得很熟悉的时候,Symbian给了我们当头一棒。该如何调试Symbian中的字符串和描述符?因为你不能直接地显示它们的内容(可以使用console-printf输出到模拟器的窗口里观看)。这里有一个小技巧可以让你显示Symbian描述符的内容。
为了达到上述目的,Microsoft Visual Studio中的"Auto Expand"可以让调试器定制规则来显示用户数据的内容。可以手动配置AutoExp.dat来达到我们的目的。在你的环境中找到这个文件,一般它位于C:/Program Files/Microsoft Visual Studio .NET 2003/Common7/Packages/Debugger,然后在它的末尾追加下面的内容:
实际上,在很多SDK的安装过程中,安装程序已偷偷完成了上面的内容。当你找到它,并准备Ctrl+v的时候,发现它已经在那儿了。重启编译器,插入断点,启动调试器之后,你会发现描述符的值被正确的显示出来了。
2.创建调试日志(log)文件
如果需要在手机上调试代码或跟踪程序执行过程,RFileLogger也许可以帮助你。这个类的功能非常强大而且容易使用。
首先要声明一个文件日志的连接并且创建一个日志文件
//打开日志文件服务的连接
RFileLogger iLog;
iLog.Connect();
iLog.CreateLog(_L("MyLoggingDirectory"),_L("MyLogFile"),EFileLoggingModeOverwrite);
//...
//关闭日志文件和服务器连接
iLog.CloseLog();
iLog.Close();
第三行的CreateLog函数有三个参数:Log路径,Log文件名,记录模式。其中记录模式有EFileLoggingModeOverwrite和EFileLoggingModeAppend两种。
例如下面的代码是我的log文件(手机上的文件系统)
C:/Logs/MyLoggingDirctory/MyLogFile
你可以把opening代码放到希望跟踪的class的ConstructL()函数里面,然后在析构函数中closing。在真正编程的时候,最好检测一下Connect和CreateLog是否返回了KErrNone。
一旦你完成了这些,你就可以向log文件中输入文本和数据了。
iLog.Write(_L("Hello World")) 27/06/2007 17:25:00 Hello World
iLog.WriteFormat(_L("Result=%d"), err) 27/06/2007 17:25:00 Result=0
iLog.HexDump(aHeader, aHeader, myPtr, 4) 27/06/2007 17:25:00 myBuf:0000:41 42 00 44 AB.D
要是不希望纪录日期和时间,可以使用下面的语句关闭它们。
iLog.SetDateAndTime(TBool aUseDate, TBool aUseTime)
实现上面的功能,需要在MMP文件中加入flogger.lib和包含flogger.h头文件。在编译执行你的程序之前,别忘了建立log文件。这没办法在代码中完成(why?),只能手工在C:/Logs/MyLoggingDirectory目录下创建log文件,否则什么日志也不会纪录。
3.使用红外进行设备调试
3.1.在手机上安装gdbstub.sis。这个文件被NOKIA SDK 放在这个默认目录里:
C:/Symbian/8.0a/S60_2nd_FP2/Debug/
3.2.关掉手机,启动FExplorer或者你的文件管理程序来创建一个名为C:/gdbstub的目录。上传一个名为gdbstub.ini文件到我们新建立的目录。内容是:
[COMMSERV]
PDD=EUART%d
LDD=ECOMM
CSY=IRCOMM
PORT=0
RATE=115200
3.3.在PC端创建C:/yyy并创建一个C:/yyy/gdb.ini文件,并输入下面的内容:
symbol-file
epoc-exec-file c:/system/apps/xxx/xxx.app
target epoc com2
break NewApplication
source
3.4.用适当的内容替代xxx和yyy。将你的IrDA端口改成com2。你可能需要在电脑上安装一个可以把IrDA映射为COM的软件(例如IrCOM2k)。
编译
abld build armi udeb
如果连接失败是因为找不到库(第一次通常都是这样),只要把epoc32/release/armi/urel下所有的内容复制到epoc32/release/armi/udeb就行了。打包并安装应用程序到手机上。
开始调试
启动FExplorer并运行C:/system/programs/gdbstub.exe。IrDA连接指示灯将开始闪烁。注意不需要connection/IrDA/active来做这些事情,因为gdbstup将自动打开红外连接。把手机放在PC的红外范围之内,随后打开PC的DOS窗口。进入C:/yyy并键入下列命令gdb.exe -nm后会出现下面的内容:
gnu gdb 4.17-psion-98r2
copyright 1998 free software foundation, inc.
gdb is free software, covered by the gnu general public license, and you are welcome to change it and/or
breakpoint 1 at 0x(some adress): file
newapplication>
gdb>
然后在gdb提示中,键入run,将会出现下列信息:
starting program:
warning: application started but no document specified.
the application may panic at some point if it is document based and if there is no existing default document.
breakpoint 1 0x(some adress): file
newapplication>
breakpoint 1, newapplication ()
at file
current language: auto; currently c++
如果你的gdb显示出"Starting program", 但在接下来没有发生别的事情,就只能通过重启手机和PC来解决。如果这样仍然没有解决的话,或许你的IrDA设备有问题。
4.使用蓝牙进行设备调试
4.1.请参照第三部分〈使用红外进行设备调试〉的步骤一。
4.2.更改第三部分〈使用红外进行设备调试〉的步骤二的RATE=9600。
4.3.创建gdb.ini。
在你的PC上创建一个目录C:/bbb并把gdb.ini文件放进去。以下是gdb.ini的内容:
symbol-file
epoc-exec-file c:/system/apps/aaa/aaa.app
target epoc com3
break NewApplication
source
用你的应用名字来替代aaa和bbb
检查第三行的端口号并用合适的端口号来代替,com编号只能在1到4之间。
4.4.编译
abld build armi udeb
如果提示错误或者警告,拷贝epoc32/release/armi/urel下的所有内容到epoc32/release/armi/udeb中即可。
4.5.更新pkg文件
现在转向你的应用程序xxx.pkg文件并改变所有路径以便从armi/udeb目录获取编译后的代码。
4.6.开始调试
4.6.1 在手机上安装FExplorer软件
4.6.2 通过FExplorer软件进入C:/system/programs/gdbstub.exe
4.6.3 检查在C:/system/libs/下的gdbseal.dll和gdbseng.dll文件
4.6.4 在手机上启动gdbstub.exe
4.6.5 在PC的DOS提示符状态进入C:/bbb 目录并运行命令 gdb.exe -nw后将会出现下列信息:
GNU gdb 4.17-psion-98r2
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or
Breakpoint 1 at 0x(some adress): file <SPAN>
NewApplication>
gdb>
然后在gdb提示中,键入run,将会出现下列信息:
Starting program:
warning: Application started but no document specified.
The application may panic at some point if it is document based and if there is no existing default document.
Breakpoint 1 0x(some adress): file < SPAN>
NewApplication>
Breakpoint 1, NewApplication ()
at file
Current language: auto; currently c++
5. 使用GNU debugger(以下简称gdb)
使用gdb能为S60应用程序做远程设备调试,在上面已经看到了一些使用gdb的例子。gdb运行在一台与设备相联接的主PC机上。运行在目标设备上的一小段"桩"程序gdbstub.exe为提供gdb调试服务。
下面做更深入些的介绍。本节不对gdb本身的实现细节刨根问底,只做使用层面上的介绍。
5.1 运行debugger
在目标设备上输入"run"命令启动debugger。有两点需要注意:
保证gdb初始化文件gdb.ini的正确性。
GUI界面上的"Run"按钮不可用,必须在命令控制台下使用"run"命令来启动debugger。
5.2 分步执行
Step:进入函数的单步执行方式。
Next:与step命令不同的是,next不会跟踪到函数内部。GUI提供一个"Next"按钮。
Continue:执行直到遇到断点停下来。GUI提供一个"continue"按钮。
Finish:没有这个命令,但GUI提供一个"finish"按钮。它能跳出当前函数,返回到调用函数。
until:执行到特定函数处或特定行,例如:
until SomeFunction
until SomeFile.cpp:117
info sources: 列举gdb识别的所有源文件。
5.3 设置和清除断点
b:在特定函数或行数处设置断点,例如:
b SomeFile.cpp:117
b CSomeFileAppUi::HandleCommandL
info breakpoints:获取当前断点列表。
delete:删除断点,带一个断点序号参数。
delete 1
clear:从特定函数或行数删除断点,例如:
clear SomeFile.cpp:117
clear CSomeFileAppUi::HandleCommandL
5.4 查看和修改变量值
print:显示变量类型和变量值,例如:
print console
变量也可以通过GUI的"Watch Expressions"窗口的输出来查看。
set var:修改变量值,例如:
set var console=0x1234
5.5 显示源码
list:如果直接输入list命令的话,就会列出光标所在行一定范围内的源代码片断。还有一种带参数的用法,例如 list File.cpp.120,此时如果指定了文件名,就要相应的指定行数。
5.6 反汇编
disassemble FunctionName:反汇编某函数,例如disassemble E32Main。
disassemble AddressRange:指定某一内存区域的汇编码,例如disassemble 0x20000000 0x20000001c。
nexti和stepi:以汇编码形式单步执行。每次单步执行后,gdb显示当前行号。
info reg pc:显示程序计数器的值,例如(gdb) info reg pc, 输出显示可能是 pc 0x20000238 536871480,分别是16进制和10进制的值。
5.7 关闭调试会话
主机方:直接输入q或者quit命令。此时关闭gdb,但目标设备上的"桩"程序转至后台运行。
设备方:按"q"键两次。
参考文献及论坛
<Symbian中文技术周刊--内存管理&设备调试专题>,Peter Jiang
<Series 60 2nd Endition SDK for Symbian OS Supporting Feature Pack 2--How to use GDB>