C++語言是案頭系統,尤其是系統軟體、大型應用軟體的主流開發語言。C++語言以其靈活性著稱,同時也更複雜。利用C++編寫健壯的代碼,更具有挑戰性。C++允許動態記憶體管理, 同時也容易導致更多和記憶體相關的問題。一般而言, 除了系統設計上的缺陷, 基於C++的軟體的缺陷和錯誤大部分都和記憶體缺陷(主要包括記憶體訪問錯誤和記憶體流失兩類)相關。 所以,消除代碼中的記憶體相關缺陷,成為程式員編寫、調試、維護代碼中的任務,也是保證軟體品質的關鍵。
本文的工作基於“863”計劃項目“面向網路海量空間資訊的大型GIS”課題。該系統是基於C++/MFC編寫,開發環境是Visual Studio .net 2003。本文基於此項目的工程實踐,總結了如何使用C++語言機制、開發環境和相關品質保證工具來預防、發現各種編譯期、運行期和記憶體相關的缺陷的方法和工具。
1 遵循C++相關的編碼規範和慣用法,預防缺陷
編碼規範是語言相關的規則,是經過實踐總結出來的經驗。良好的編程標準將有效地協助開發人員避免開發有潛在危險的代碼。一般來說,為了減少記憶體缺陷,應該遵循下列編碼規則[1]:
(1)基類或者帶有虛函數的類應該將其解構函式聲明為虛函數。
(2)在建構函式中防止記憶體流失,在解構函式中不要拋出異常。
(3)使用對應形式的new和delete。即:用delete來釋放new申請的記憶體,delete[]釋放new[]申請的記憶體。
(4)指標在使用前必須初始化,指向動態記憶體的指標在釋放後應立即置為空白。
(5)如果類建構函式中分配了資源,那麼需要顯式提供拷貝建構函式和賦值操作符,並且在解構函式中釋放資源。
值得重視的是C++中的慣用法RAII。RAII核心思想是利用對象來管理資源,在對象的建構函式中擷取資源,在其解構函式中釋放資源[2]。為了保證動態申請的記憶體能在即使出現異常的情況下仍能釋放,比較理想的方法是使用局部變數來管理動態記憶體的所有權(ownership),就是所謂的智能指標。STL中的auto_ptr就是為解決資源所有權問題設計的,但是缺少對引用數和數組的支援並且不能用在STL容器中。Boost庫[3]提供的智能指標相對成熟,實用價值高。其中,shared_ptr安全執行緒並且可以用在STL容器中。具體樣本參考文獻[3]。
1.1 編碼規範檢查工具 CodeWizard
CodeWizard能夠對來源程式直接進行自動掃描、分析和檢查。一旦發現違例,產生資訊告知與哪條規則不符並作出解釋。以CodeWizard 4.3 為例,其中內建了超過500條編碼通訊協定。CodeWizard可以選擇對於當前的工程執行哪些編碼通訊協定。CodeWizard可以和VC++緊密整合,安裝完畢以後,VC++中有CodeWizard工具條。
1.2 代碼檢查工具 PC-Lint
PC-Lint可檢查編譯器不易發現的錯誤。PC-Lint可對100多個C庫函數進行檢查,可以發現標準C/C++代碼中的1 000多個常見錯誤。要把PC-lint和Visual Studio整合在一起,需要自己配置。Jon Zyzyck提供了一個報告產生器,可以協助完成這個工作。可在http://www.ddj.com下載。文獻[4]說明了如何在VC++環境中整合PC-Lint。