C/C++大型項目錯誤管理
在C/C++大型項目中,錯誤管理在項目中起著舉足輕重的作用,以我自己的項目經驗以及觀摩其他項目,錯誤管理對項目框架以及開發效率有著很大的影響。對於錯誤管理的認識大致分為三類:
- 剛剛開始寫程序的新手,滿篇程序看不到一處關於返回出錯的處理,更不用說出錯管理了。說明他沒認識到出錯管理的重要性
- 程序中到處都能看到關於出錯的處理。認識到了錯誤,但是處理方式欠缺
- 程序中幾乎不會很明顯的看到關於錯誤的處理。這是錯誤管理的最高境界。
錯誤管理,涉及到程序的健壯性,可恢複性,可靠性,高效性。在出錯的情況下,程序任然能夠相對穩健高效的執行。
下麵我談談我自己在C/C++項目開發中關於錯誤管理的經驗。
對於C/C++係統API,都提供了errno.h頭文件,裏麵已經定義了絕大多數係統已知的錯誤以及其對應的錯誤提示。 參考《linux中出錯處理》
一般係統自帶的錯誤定義以及出錯提示都不能很好的滿足實際的項目需求,畢竟項目中很多都涉及到具體業務,如果籠統的使用係統定義的錯誤號以及描述,並不能很快的定義錯誤位置。通常需要我們自己重新封裝並定義錯誤。
《The Art of Unix Programming》中有一個原則說的非常好:Rule of Repair: When you must fail, fail noisily and as soon as possible。當程序遇到無法修複必須報錯的時候,就讓它立即用很明顯的方式報錯。這句話很簡潔,但是缺描述出了關於錯誤管理的理念。如果一定要出錯,就很明顯的方式來表達,目的就是為了很迅速精準的定位錯誤。出錯不是期望,出錯管理也不是目的,目的是為了在出錯之後能很快的定位錯誤使得程序能夠很快的恢複。
為了快速定位錯誤,有三個宏非常有用:
__FILE__ //文件名 __FUNCTION__ //函數名 __LINE__ //當前行號
一般針對不同的業務會有不同的模塊。自定義錯誤號的方式如下:
//EBASE最高位是1,保證錯誤號是負數,符合編程習慣 #define EBASE 0X80000000 //串口業務模塊 #define ESERIAL EBASE + 0XC8 #define ESERIALTIMEOUT ESERIAL + 1 //串口超時 #define ESERIALREAD ESERIAL + 2 //讀串口錯誤 //.... //HTTP業務模塊,與ESERIAL之間有200的差距,這樣串口業務模塊可以有200個錯誤號 #define EHTTPSERVICE EBASE + 0X190 #define EHTTPTIME EHTTPSERVICE + 1 #define EHTTPGET EHTTPSERVICE + 2 //... //與EHTTPSERVICE有200差距,這樣HTTP也可以有200個錯誤號 #define EGSM EBASE + 258 //....
模塊化定義錯誤,通過錯誤號區間可以很快的查閱錯誤模塊。例如錯誤號是 -202,通過對照,毫無疑問是串口模塊出錯了。
接下來就是錯誤的翻譯了。所謂錯誤翻譯就是將錯誤號翻譯成具體的語句。可以選擇將錯誤描述與錯誤號寫入Excel表中,然後導出XML文件,在程序中錯誤描述可以直接解析對應XML中錯誤號的描述即可。
另一種比較常見的方式就是直接用宏寫在一個頭文件中。當然,__FILE__, __FUNCTION__這些必不可少。
日誌文件記錄了程序後台運行狀況以及出錯前一刻程序正在做什麼,一般可以從日誌文件的數據分析程序的行為並定位錯誤。對於日誌文件,我想C/C++程序員都會寫,這裏我就不多說。一般打印錯誤提示的同時都會伴隨著寫日誌。
一般都會用宏來寫打印錯誤和寫日誌的操作,關於如何寫我這裏不多說,我想很多人都會。這裏我想強調的事關於打印錯誤信息和寫日誌一定要設置開關。在實際項目中,我經常會遇到這種問題,當有很多地方都需要打印和記錄log的時候,程序執行的非常慢,當我把寫日誌去掉,程序立馬就能很快的運行。所以,設置開關是很有必要的:
#ifndef LOG_OFF #define WriteLog(file, line, function, desc) \ //...一些寫日誌和打印操作 #else #define WriteLog(file, line, function, desc) #endif
這樣,在程序中可以很好的控製開關。提高效率
最後更新:2017-04-02 06:51:50