52RD上曾有朋友让我写一些调试技巧方面的文章.调试对于软件是十分重要的,但却不是一篇二篇文章能讲清楚的.有不少调试技巧都是零零碎碎的东西,用的时候能很容易使用,但要写出来时,却仍是比较麻烦的.html
MTK的调试通常来讲能够分为仿真调试与手机调试.这两种调试对于研发新功能,修改BUG,研究算法都是十分重要的.固然,这两种调试也有差别,有时会出如今模拟器运行正常,在手机却运行失败,或者相反,这就突出了软件模拟环境与硬件手机环境的差异.缘由多是各类各样的,好比多是有些硬件软件没有办法模拟,有些新功能对硬件依赖强,不能模拟,新软件的有些函数只能在手机上运行,没有写相应的模拟器代码.等等缘由都会致使二者差别.这里不一一赘述,你们知道模拟器和手机有差别就好了.算法
模拟器调试具备直观,快速,追踪方便能优势,受到不少MMI开发者的喜欢.而有关模拟器的调试,其余也就是VC调试功能的使用.因为国内软件教育重编程,算法,轻调试,因此不多有系统的调试方书的书.在开发过程当中,我也见过许多人压根就不使用模拟器,他们认为模拟器也就是在没有手机的时候使用.详细讲解模拟器的调试就放到之后,由于模拟器断点,内存,堆栈,变量各个方面的调试,详细写来均可以成一篇文章.这里先讲一个手机调试的TRACE使用.之前曾写过一篇DUMP调试的文章.经过出错的DUMP信息查找错误.有兴趣的朋友能够参考. Detail_RD.Blog_blogercn_19169.html编程
1.在MTK平台,咱们最常使用的TRACE函数是kal_prompt_trace函数,这个函数是系统提供给咱们的用于在catcher里调试错误的.在这个函数不能使用的场合,有时咱们会使用函数system_print或者dbg_printf,这两个函数能够不使用catcher的状况,使用WIN自带的工具超级终端来调试程序.有时驱动的朋友会本身用函数PutUARTBytes写自已TRACE函数,这些函数可使用超级终端调试,以下,就是别人写的一个TRACE函数.打印某一块数据的内容,经常TRACE内存数据,指定地址,指定大小网络
void perun_dump(void *buf, prn_int16 size)函数
{工具
#ifdef PRN_TRACE_OPEN优化
#ifdef MMI_ON_HARDWARE_Pui
char str[2048];编码
char *ptr = (char*)str;.net
char *ptr1 = buf;
int i = 0;
memset(str, 0, sizeof(str));
strcpy(ptr, "[Perun_dump]: ");
ptr += strlen("[Perun_dump]: ");
while (i < size)
{
sprintf(ptr, " %02x", *ptr1);
ptr += 3;
++ptr1;
++i;
}
sprintf(ptr, "\r\n");
PutUARTBytes(0, (kal_uint8 *)str, (kal_uint16)strlen(str));
#endif
#endif
}
也能够写一个像MTK自带的同样的函数来TRACE,以下,该函数也是能够运行在终端中:
Void perun_trace(char *fmt, ...)
{
#ifdef PRN_TRACE_OPEN
#ifdef MMI_ON_HARDWARE_P
va_list list;
char buf[2048];
char *ptr = (char*)buf;
memset(buf, 0, sizeof(buf));
strcpy(ptr, "[Perun_trace]: ");
ptr += strlen("[Perun_trace]: ");
va_start(list, fmt);
vsprintf(ptr, fmt, list);
va_end(list);
strcat(buf, "\r\n");
buf[2047] = 0;
PutUARTBytes(0, (kal_uint8 *)buf, strlen(buf));
#endif
#endif
}
2.TRACE语句的编写是十分重要的.如何写出的TRACE既能在仿真下使用,也能在手机中使用,我通常会使用以下的格式:
#ifdef WIN32
#define MYTRACE printf
#else
#define MYTRACE(...) kal_prompt_trace(MOD_WAP, __VA_ARGS__)
#endif
通过以下的封装,MYTRACE就能够既能在手机上运行,也能在电脑中运行, 而且我已经消除了MTK自带的函数与printf在调用上的不一样.顺便说一下,模拟器调用函数MYTRACE时,会在控制制输出该函数的打印信息.手机调用MYTRACE时,会在filiter为MOD_WAP时输出信息.
3.有时为了便于观察,我会为个人TRACE语句添加一个前缀,好比我本身的TRACE前面添加十个>或者我本身的拼音名字,我会以下修改个人MYTRACE:
#ifdef WIN32
#define MYTRACE printf
#else
#define STR(s) #s
#define MYTRACE(...) kal_prompt_trace(MOD_WAP, STR(>>>>>>>>>>)##__VA_ARGS__)
#endif
通过这样的改进,个人TRACE在输出信息时,信息头就是个人名字,我可使用查找所有功能把我须要的TRACE全抓出来.若是你对#号的使用,有疑问,请本身查找相关资料
4.种种迹象和从理论上看来,TRACE和MMI_ASSERT是调试的好帮手,但在发布软件时,带上了这个会引来没必要要的麻烦.MMI_ASSERT增长了系统重启的频率.TRACE增长了系统的ROM,RAM和CPU的开销.在工做中,咱们曾经发现一款手机,因为ROM过于紧张,添加几条TRACE就会出现编译错误,去掉TRACE就编译经过了,致使出了BUG调试十分的麻烦.如何写一种使用时能够TRACE错误,不使用时又不占用系统资源的TRACE呢,我见许多人这样处理,由于NULL会被编译器优化点,后面括号变成一个表达式了.表达式对系统的开销天然小于函数了.
#ifdef DEBUG_KAL
#define MYTRACE(...) kal_prompt_trace(MOD_WAP, __VA_ARGS__)
#else
#define MYTRACE NULL
#endif
我通常这样操做.
#ifdef DEBUG_KAL
#define MYTRACE(...) kal_prompt_trace(MOD_WAP, __VA_ARGS__)
#else
#define MYTRACE //
#endif
我曾经认为这样写能够在不使用时,把宏函数变为注释符,但个人一个朋友认为这样写,并不能把个人函数变成注释符,他的道理是双斜线会被编译器外忽略掉,我认为是有道理的,后来个人朋友通过思考,写出以下的TRACE,经过一个反斜杠的链接符,哄编译器在展开宏时把两个斜杠连起来组成注释符,这个写法有些古怪,下面的单个斜杠必须顶格写,以保证通过链接合,两斜杠之间没有空格从而在被编译时与后面的代码组成注释行.但这样写的一个致命的缺陷是会让许多人看不明白.另外一个缺陷时不美观
#ifdef DEBUG_KAL
#define MYTRACE printf
#else
#define MYTRACE /\
/
#endif
5.有关C语言的古怪用法,据
#define DBG_PRINTF(_x_) \
do{ \
printf("%s(%d)--:",__FILE__,__LINE__);\
printf _x_; \
}while(0);
当时怎么想都不明白为何会有这么古怪的使用printf _x_;后来才发现使用时要加双层括号才能正常使用。
6.在手机与网络,手机与电脑的交互过程当中,有时咱们须要TRACE数据包的内容,特别在显示不正确或者不精确的状况下,须要研究数据包的数据是使用UTF编码,还UCS2编码,仍是ASC编码,这时咱们就须要TRACE数据的字节内容,从而便于分析。我通常使用下面这个本身随手写的函数来实现.
static U8 TraceUni(U8 *str, U8 len)
{
U8 *tempstr,*tempascstr;
U8 i;
tempstr = str;
kal_prompt_trace(MOD_MMI, "XXXXXXXXXXXXXXXXXXXXXXXX Trace mmi_msg_handle_new_msg_ind is start XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
if (*(tempstr + 1) == 0x00)
{
UnicodeNToAnsii((S8*)tempascstr,(S8*)tempstr,len );
kal_prompt_trace(MOD_MMI, "jone trace, the string = %s", tempascstr);
}
else
{
for (i = 0; (*tempstr != NULL) || (*(tempstr+1) != NULL) && (len-- != 0); i++)
{
kal_prompt_trace(MOD_MMI, "jone trace, the string[%d] = %x", i, *(tempstr++));
}
}
kal_prompt_trace(MOD_MMI, "XXXXXXXXXXXXXXXXXXXXXXXX Trace string is end XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
return 0;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/blogercn/archive/2009/10/28/4739732.aspx