在開發過程中,需要經常輸出日志以協助調試和分析問題,一個良好的日志輸出能夠快速的幫助我們定位和分析問題。在一些linux平台嵌入式開發過程中,開發過程中對單步調試支持的並不好,它的調試很大一部分是借助於日志來完成。對最近一段時間嵌入式開發的反思與總結,個人感覺,日志輸出時盡量做到以下幾點: 1、個人認為可以把日志內容分為:定位日志和錯誤報告日志,除此兩者之外的其他調試日志內容在調試完畢提交代碼的時候就要刪除掉,這樣可以減少無關日志的輸出,便於查看日志內容和定位問題,同時也可以減少多余的代碼量,增加代碼的清晰度,便於維護代碼。 一些多余的調試日志例如代碼段1所示,對於一些不方便單步調試的開發,其單步調試主要借助日志來完成,因此這樣的日志輸出會更多。 [cpp] 代碼段1 int Open(char* pFileName/*IN*/) { printf("into func:Open ");//------------多余的調試日志 if(NULL == pFileName) { printf("pointer of file name is NULL "); return -1; } if(NULL != g_logfile) { printf("logfile has been opened"); return 2; } printf("into func:Open,before fopen ");//------------多余的調試日志 g_logfile = fopen(pFileName,"rw+"); if(NULL == g_logfile) { printf("logfile open fail"); return -2; } return 1; } 定位日志:是指用於提示某個功能已經開始執行或已經執行完成,這種類型的日志可以隔離問題域,一旦程序發生問題,可以根據定位日志縮小排查問題的范圍,進而提高問題解決的速度。 錯誤日志:是指提示代碼中發生了某個具體問題,對於代碼中可以預料到的錯誤和try...catch捕捉到的異常都需要進行有效且清晰的日志輸出。例如打開文件失敗的時候,在返回之前就應該有日志輸出,可參考的條目2中的代碼段3 2、不要直接使用庫函數(例如printf、cout之類)進行輸出,而是每個cpp文件自定義一個日志輸出函數(如果是面向對象,則為每個類定義一個私有的日志輸出成員函數),在該自定義的日志輸出函數中在調用輸出庫函數,這樣方便以後統一更改日志輸出,例如想以後引入log4cpp的話就只需要修改自定義的日志輸出函數即可,而不需要修改每一個日志輸出之處: 例如: 原來代碼: [cpp] 代碼段2: int Open(char* pFileName/*IN*/) { if(NULL == pFileName) { printf("pointer of file name is NULL "); return -1; } if(NULL != g_logfile) { printf("logfile has been opened"); return 2; } g_logfile = fopen(pFileName,"rw+"); if(NULL == g_logfile) { printf("logfile open fail"); return -2; } return 1; } 將其修改為不直接引用輸出庫函數printf的形式,例如: [cpp] 代碼段3: int Open(char* pFileName/*IN*/) { if(NULL == pFileName) { _DisplayLog("pointer of file name is NULL "); return -1; } if(NULL != g_logfile) { _DisplayLog("logfile has been opened"); return 2; } g_logfile = fopen(pFileName,"rw+"); if(NULL == g_logfile) { _DisplayLog("logfile open fail"); return -2; } return 1; } 上述使用的自定義日志輸出函數為: [cpp] 代碼段3 void _DisplayLog(char* pMsg/*IN*/) { if(g_bUseLog && NULL != pMsg) { www.2cto.com printf("[test.cpp]: "); printf("%s",pMsg); printf("\n"); } } 3、日志文件應該可以開關,即不需要修改代碼和重新編譯就能打開或關閉日志的輸出,這一點可以通過定義一個開關變量來實現,在自定義日志輸出函數中根據該開關來決定是否進行日志輸出,如代碼段4中所示。 4、在每個cpp文件的自定義日志輸出函數中為每條日志默認加上文件名,例如: [test.cpp]: 日志內容 這樣當項目較大,日志較多時比較容易定位每條日志的位置,如代碼段4所示。 5、日志輸出應該簡單、清晰,描述清除問題即可。在以往的代碼開發中見到很多人(其實我以前也如此做過)這麼寫日志:printf("***********************************");這樣輸出本來是想增加該條日志的醒目程度,但是往往,這裡增加一條,那裡還會增加以後,不久之後就會發現滿屏的亂七八糟的東西,非常不利於調試。 6、每條日志占用一行。