原文
如果世界上有乙個人能夠保證一次寫出來的**是百分之百正確的,那麼毫無疑問,他一定是世界上最優秀的程式設計師,沒有之一。為什麼要求**寫好過後要進行充分的自測 ( 包括單元測試和整合測試 ) ?就因為是人皆會犯錯,使程式就會有 bug 。作為一名軟體開發人員,必須要學會對程式進行測試,也就是要學會程式的除錯。
一般而言,對**的除錯有以下幾種方法:
第一,憑肉眼看 。在開發階段,我們編寫的每一行**都需要用我們的「火眼金睛」多審查幾遍。如果要問,最好的**除錯工具是什麼?我認為是人眼。不管是**還是文件,在用工具檢查之前,都需要先過了我們眼睛這一關。
第二,對**進行編譯,以發現語法錯誤 。編譯器能夠幫助我們發現**中存在的語法錯誤,但對於那些隱蔽性的錯誤 ( 如邏輯錯誤等 ) 無能為力。
第三,用**檢查工具 ( 如 pclint 等 ) 來走查** 。如果**編譯通過,並不表示它就沒有問題了。在學校的時候,我們一般認為只要程式能夠執行就可以了。但在實際的軟體開發專案中,程式能夠跑起來,只是「萬里長征走完了第一步」。用**檢查工具可以發現很多編譯器無法發現的錯誤,如變數定義了未引用、不同資料型別之間相互賦值、函式未宣告便被呼叫等。
第四,對**進行除錯 。對於執行正常而輸出結果不正確的程式,我們可以用設定斷點並進行單步跟蹤除錯的方法來發現其中存在的問題。例如,在 vc++ 6.0 裡面,可實現對**的單步除錯,並輸出變數在某一步產生的值,可據此判斷程式的邏輯的正確與否。
第五,對程式的日誌檔案進行分析 。對**的單步除錯只在**行數較少的時候比較適用,如學校教材上面的程式。但在實際的軟體專案中,**少則幾千行,多則數萬行,用單步除錯的方法顯然不恰當。為了跟蹤某一變數值的變化,用該方法可能要花費幾個小時,這對工作效率產生了嚴重影響。為了解決大程式檔案**除錯問題,日誌系統應運而生。在程式中的重要地方列印日誌,之後對產生的日誌進行分析,可找到對應**的問題。因此,日誌檔案分析成了大型軟體專案中**除錯的主要手段。
1. 什麼是日誌檔案?
在業務軟體系統中大量使用日誌,日誌能夠起到「按圖索驥」的作用,它對於故障定位和系統正常執行維護具有舉足輕重的作用。
日誌檔案是程式中寫日誌函式產生的記錄程式執**況的檔案。寫日誌函式也是用 c 語言編寫的,同 c 函式一樣被呼叫。在恰當的地方呼叫該函式,可對整個程式的執行狀況有乙個全面的了解,方便對程式的跟蹤除錯。
2. 有關日誌等級和日誌配置說明
(1) 日誌等級
事有輕重緩急,日誌資訊也有重要與不重要之分。一般按照重要程度,將日誌等級分為幾類。在作者參與過的軟體開發專案中,共有 7 個等級,用巨集定義表示如下:
// 日誌等級定義
#define log_fatal (int)1 // 嚴重錯誤
#define log_error (int)2 // 一般錯誤
#define log_warn (int)3 // 警告資訊
#define log_info (int)4 // 一般資訊
#define log_trace (int)5 // 跟蹤資訊
#define log_debug (int)6 // 除錯資訊
#define log_all (int)7 // 全部
開發人員根據所要列印的日誌的具體情況採用不同的日誌等級。
(2) 日誌配置
由於不同產品程式行數、部署情況、實現功能等的差別,對日誌列印的要求也不盡相同,因此需要有配置來控制日誌的產生數量和顯示情況。
在配置檔案中,有乙個專門的 [log] 配置段,其中的配置項如下:
[ log ]
; 日誌等級 , 0-fatal 1-error 2-warn 3-info 4-trace 5-debug 6-all
loglevel =
; 每個日誌檔案的最大容量
logmaxsize =
; 是否輸出該條日誌在**中的行數 , 1-yes 0-no
logposition =
其中, loglevel 用於控制列印日誌的等級,**中日誌等級比配置值大的日誌資訊均不在日誌檔案中顯示; logmaxsize 用於控制生成乙個日誌檔案的大小的上限,超過該值後,便重新生成檔案; logposition 用於控制是否在日誌檔案中顯示**行數,方便將日誌與**對應起來。
3. 如何呼叫寫日誌函式?
日誌函式的呼叫遵循一般函式的呼叫規則。有兩類寫日誌函式,如下所示:
(1) 第一類形如: writelog(loglevel, loginfo) 。其中,引數 loglevel 指日誌等級 ( 見第 2 節中的說明 ) ;引數 loginfo 是具體要列印的日誌資訊,我們據此資訊來檢查程式的運**況。該函式的呼叫示例如: writelog(log_info, "the value of this integer is 3.") ,日誌等級為 log_info ,日誌資訊為「 the value of this integer is 3. 」( 該資訊會輸出到日誌檔案中 ) 。
(2) 第二類形如: writelogex(loglevel, loginfo, parainfo) 。這是擴充套件的日誌函式,不但能夠輸出日誌資訊,還能夠在日誌資訊中顯示變數的值。該函式的呼叫示例如: writelogex(log_info, "the value of integer iint is %d.", iint) ,該日誌要輸出整型變數 iint 的值,可以將該函式的呼叫與 printf 函式的呼叫比較起來看 ( 可以認為writelogex 函式只是在 printf 函式中增加了乙個日誌等級引數 ) 。
4. 編寫日誌的基本原則、基本要求和位置要求
日誌編寫的總體原則是簡單清晰、便於排查問題。
(1) 日誌編寫的基本原則
1) 顯式輸出,關鍵資訊必須輸出;
2) 在編碼時使用正確的日誌級別, error 錯誤和 warning 錯誤必須反應出實在的含義,不是特別嚴重的問題不能將日誌等級定義為 log_fatal ;
3) 在寫日誌描述時,要使用正常簡單易懂的語言,不能使用晦澀難懂的語言或某些專業術語;
4) 在極少數特殊情況不希望使用者知道時,可使用特殊日誌標記;
5) 為了寫出優美的**,在自己修改或新增**的地方,都要正確的打上標記 (包括作者、日期資訊等 ) ,方便追蹤版本的演進情況。
(2) 日誌編寫的基本要求
1) 分多條資訊分別輸出,不要企圖一次將所有資訊列印出來;
2) 分時輸出;
3) 必須分日誌級別,這樣可根據等級迅速對日誌進行分析;
4) 控制日誌資訊的條數,不重要的資訊盡量不要列印日誌。
(3) 輸出日誌的位置要求
1) 所有的輸入輸出,包括收訊息和發訊息都要求輸出日誌;
2) 關鍵控制點必須輸出日誌;
3) 呼叫底層或第三方軟體,必須輸出日誌,而且對不可靠底層,必須加上 begin/end 兩行日誌;
4) 對方系統處理時間必須輸出日誌,以利以後維護時快速定位效能問題。
此外,作者認為,在編寫日誌時還需要注意以下幾點:
1) 在編寫日誌時需要注重日誌細節,目標是為了方便以後維護,在遇到問題時,可以快速定位問題。
2) 不要在同一行中寫意思重複的日誌。
3) 日誌需要足夠的精簡,不要隨意換行。
4) 日誌中欄位之間可以用空格或其它符號分斷,不能將日誌一直連續而不將其分斷,盡量使日誌本身具備進行「識文斷句」的能力。
5) 對於日誌中的特殊資訊 ( 如會話號、 ip 位址等 ) ,用特殊的符號進行標識,其主要目的是為了便於搜尋。
5. 總結
日誌系統在軟體程式中占有非常重要的地位,日誌檔案是排查程式問題的主要工具,是程式除錯的利器。作為一名合格的軟體開發工程師,一定要學會日誌函式的靈活呼叫及準確通過日誌檔案來定位程式問題。
「實踐出真知」,只有通過不斷的積累和總結,才會對日誌有更全面的認識。
程式除錯的利器 日誌
如果世界上有乙個人能夠保證一次寫出來的 是百分之百正確的,那麼毫無疑問,他一定是世界上最優秀的程式設計師,沒有之一。為什麼要求 寫好過後要進行充分的自測 包括單元測試和整合測試 就因為是人皆會犯錯,使程式就會有 bug 作為一名軟體開發人員,必須要學會對程式進行測試,也就是要學會程式的除錯。一般而言...
程式除錯的利器 日誌
在網上看到了一篇關於除錯方法 日誌的講解,想要收藏下來,便於以後的檢視。如果世界上有乙個人能夠保證一次寫出來的 是百分之百正確的,那麼毫無疑問,他一定是世界上最優秀的程式設計師,沒有之一。為什麼要求 寫好過後要進行充分的自測 包括單元測試和整合測試 就因為是人皆會犯錯,使程式就會有 bug。作為一名...
除錯程式的利器 printf
宣告 這些內容主要是面向c語言的初學者,尤其是正在學習c語言的學生。當排除了所有的語法錯誤,但執行結果卻不正確時,很多初學者往往束手無策,只好求助老師了,老師,我這個程式沒錯,但結果不正確 這是在上機課上經常聽到的聲音。初學者缺乏經驗,也缺乏耐心。殊不知每個程式設計師都是在不斷的和錯誤鬥爭的過程中成...