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