在軟體開發過程中需要使用的工具類型實屬眾多,從需求建模到軟體測試,從代碼編譯到工程管理,這些工具都對項目有著不可替代的作用。莊子有雲,「吾生也有涯,而知也無涯,以有涯隨無涯,殆已」。代入到項目開發中就是說,如果對知識點無差別的全面攻擊,不僅會導致所學甚泛卻無一深入的尷尬,也會佔用太多的有效時間從而影響項目進度。作為一個C++遊戲伺服器開發者來說,我們時刻肩負著線上遊戲開發和維護任務,可以優先學習對自己工作最常用且最重要的,解決實際問題最為緊迫。本文對一些常用工具給出了介紹和指引,包括調試器、內存洩露檢查工具、代碼覆蓋工具、抓包工具、性能分析工具、靜態代碼檢查工具、high cpu分析工具以及Lua腳本開發工具,旨在幫助經驗不足的C++伺服器開發工程師解決代碼問題和提升代碼質量,從而提升自己和團隊的工作效率。
調試器通常,調試(debugging)是指發現缺陷並改正的過程。如果代碼中存在缺陷,我們首先要識別造成缺陷的根本原因(root cause),這個過程就稱作調試。找到根本原因後,就可以修正缺陷。在軟體開發周期中,調試並修正缺陷的時間可能遠多於寫代碼的時間,有得心應手的工具可以節省調試時間無疑是非常重要的。
在linux下一般使用 GDB(GNU symbolic debugger)進行調試,它是一個受通用公共許可證即GPL保護的自由軟體,可以調試多種語言。
對GDB有一定了解的人會發現,GDB對STL的調試比較困難,這裡推薦一個GNU提供的調試工具 ,使用python實現,支持C++11特性。
同時你可以使用一些前端工具如XXGDB,DDD等。它們都有圖形化界面,因此使用更方便。也可以使用WinGdb,利用Visual Studio的IDE進行Linux遠程調試。
另外,如果你再程序中發現了和系統調用相關的問題,使用strace可以快速定位。strace能夠跟蹤進程執行時的系統調用和所接收的信號,並將相關調用信息放在輸出流中。
在windows下一般使用 Visual Studio自帶的調試工具,除此以外,也推薦使用WinDbg,它是微軟發布的一款相當優秀的源碼級(source-level)調試工具,可以用於Kernel模式調試和用戶模式調試,還可以調試Dump文件。
內存洩漏(memory leak)是很多C++代碼中比較容易出現的問題。內存洩漏也稱作「存儲滲漏」,意思是說當你用動態存儲分配函數動態開闢了一塊內存空間,在使用完畢後忘記了釋放,導致這塊空間在進程結束以前都不再可用。偶爾發生的內存洩漏可能並不嚴重,但是以下情況會導致嚴重的系統故障:
1)程序運行後置之不理,並且隨著時間的流失消耗越來越多的內存;
2)程序能夠請求未被釋放的內存(比如共享內存),甚至是在程序終止的時候;
3)洩漏在發生在作業系統內部或者系統關鍵驅動中;
4)內存非常有限,比如在嵌入式系統或便攜設備中;
我們可以使用內存洩露檢查工具在測試環境下監視進程的運行並獲取詳細測試報告,然後對有內存洩漏的代碼段各個擊破,從而規避嚴重故障的風險。
在Linux環境下推薦使用valgrind,它是一款用來定位c/c++程序中內存相關錯誤的工具集,功能包括內存洩漏、使用未初始化的內存、讀/寫已釋放的內存、讀/寫內存越界等
Windows Leaks Detector是下專門用於解決windows環境下內存洩漏的工具,基於Win API調用鉤子實現,能夠探測任何Win32應用程式中的資源洩漏(內存,句柄等)。
如果你安裝了WinDbg, umdh工具也會被附帶安裝,和windbg.exe在同一級目錄下。輕量級的umdh也可以用於定位內存洩露,使用起來非常簡單。
代碼覆蓋率(code coverage rate)是反映測試用例對被測軟體覆蓋程度的重要指標,也是衡量測試工作進展情況的重要指標。在代碼邏輯比較複雜的情況下,測試工作往往只能覆蓋到顯而易見的邏輯分支,而更多的深層次的邏輯分支則不容易被測試人員發現。為了保證測試的覆蓋率,有些開發人員會嘗試協助測試人員寫出所有的測試用例,這不僅會犧牲大量的寶貴的開發時間,同時也擁有一定的難度,最重要原因就是因為測試難以量化。而代碼覆蓋工具就是用來量化代碼測試的覆蓋率,讓測試人員可以直觀的發現那些沒有覆蓋到的代碼分支。
4.性能分析工具軟體的性能是軟體質量的重要考察點,不論是服務端還是客戶端程序,性能都是用戶體驗的關鍵,主要包括性能表現和穩定性兩個方面。解決性能問題最基本的方法是開發者對代碼進行review,同時也可以使用工具對代碼進行性能分析(profiling)。
在Linux環境下推薦使用gprof,它是gnu binutils工具之一,默認情況下Linux系統中都帶有這個工具,它能夠精確地給出函數被調用的時間和次數和函數調用關係。
在windows環境下可以使用visual studio自帶的profiling工具,工具的界面入口 Config Properties -> Linker -> Advanced -> Profile,但是需要visual studio2008以上版本。如果你使用的是更早的版本,可以使用C++ Profiler。
另一款頗有口碑的軟體是AQTime,它能夠收集程序運行時關鍵的性能信息和內存/資源分配信息,並提交概要報告和詳細報告,還提供所有的程序優化處理工具,囊括了自定義過濾器、圖形化的調用層次結構一直到原始碼瀏覽等內容,是完整的性能和調試工具集,功能非常強大。
抓包(packet capture)就是將網絡傳輸發送與接收的數據包進行截獲、重發、編輯、轉存等操作,也用來檢查網絡安全,也經常被用來進行數據截取等。在項目開發過程中,特別是B/S或C/S模型的項目中,伺服器和客戶端中間的交互相關問題很難定位,需要額外看懂很多源碼,並且調試起來相當費時。網絡抓包工具的設計目的就在於此,對於協議次數、協議順序、協議內容是否都與編碼和設計的預期一致這類問題,可以直接獲取到二進位的tcp或者udp流的內容並導出到文本,方便開發者解決複雜交互問題。
6.靜態代碼檢查工具靜態代碼檢查(static code check)是指使用自動化工具軟體對程序原始碼進行檢查,以分析程序行為的技術,應用於程序的正確性檢查、安全缺陷檢測、程序優化等。靜態代碼檢查承諾無需開發人員費勁就能找出代碼中已有的缺陷。當然,這些承諾並不是一定能兌現。儘管如此,好的靜態分析工具仍然是工具箱中的無價之寶,因為它可以不需要運行就可以幫助你檢查代碼中的潛在風險。
在Linux環境下推薦使用cppcheck,它作為編譯器的一種補充檢查,cppcheck對產品的原始碼執行嚴格的邏輯檢查,包括自動變量檢查、數組的邊界檢查、class類檢查、過期的函數調用檢查、異常內存使用、釋放檢查、內存洩漏檢查、作業系統資源釋放檢查、異常STL函數使用檢查、代碼格式錯誤、性能因素檢查這些類型,覆蓋範圍非常全面。
在windows環境下可以使用PC-Lint,功能可媲美cppcheck。
由於PC-Lint是商業化的軟體,不便於大家學習和使用,但是如果你只需要使用C語言進行開發,可以使用開源程序靜態分析工具splint。
另外,介紹一個Google使用的C++代碼規範檢查工具Cpplint。如果你當前也使用Google C++代碼規範,那麼你很有必要使用Cpplint,它是一個python腳本,使用簡單的命令即可校驗你的代碼書寫是否符合規範。它支持linux和windows兩種環境,並可以嵌入visual studio。
High CPU監控工具可以用於監控和定位CPU佔用比較高的進程和線程,獲取當時的堆棧信息來定位代碼段,相比profiling工具更加直觀。
ProcDump是一個監視 CPU峰值命令行工具,適用於windows環境,以attach的方式進行使用,當達到預設的CPU峰值時會生成當時的轉儲文件。 ProcDump還可以對懸窗(hung window)和未處理的異常(unhandled exception)進行監控,並可以基於系統性能計數器的值轉儲。它也可作為一般進程轉儲實用工具,可以在其他腳本(比如python)中嵌入。
Windows環境下另一個推薦使用的工具是process explorer,它是由Sysinternals開發的Windows系統和應用程式監視工具,不僅結合了Filemon(文件監視器)和Regmon(註冊表監視器)兩個工具的功能,還增加了多項重要的增強功能。包括穩定性和性能改進、強大的過濾選項、修正的進程樹對話框(增加了進程存活時間圖表)、可根據點擊位置變換的右擊菜單過濾條目、集成帶原始碼存儲的堆棧跟蹤對話框、更快的堆棧跟蹤、可在 64位 Windows 上加載 32位 日誌文件的能力、監視映像(DLL和內核模式驅動程序)加載、系統引導時記錄所有操作等。
Linux環境下沒有發現整合好的對應工具,但可以使用pstack導出線程堆棧,為了輔助pstack捕獲進程和cpu相關信息,還需要top、atop、pidstat、ps、pstree這類命令來監控定位High CPU進程,最終達到的效果與windows下面的兩款工具是一致的。
Lua腳本是一種與C/C++結合非常緊密的動態語言,自身就是由C代碼實現的。由於它簡單而又高效的特性,當前已經成功運用於各類行業軟體中,在遊戲開發領域更是有著其不可撼動的地位。作為遊戲開發者,擁有一套高效易用的lua開發環境也同樣重要。
由於Lua語法相對簡單,很多編輯工具都能夠為Lua提供語法高亮或者語法跳轉功能,鮮有調試功能,調試Lua僅限於加入print函數重新運行,調試效率非常低。所以推薦使用Lua Studio,適用於windows環境,IDE本身帶有代碼美觀的功能,可以動態地以attach形式附著到任何進程中進行調試,並且自帶腳本熱點函數性能分析工具,功能比較全面。
在Linux環境下可以使用Eclipse LDT,仍然具有調試功能。
lua的靜態檢查工具只有Lua-Checker,但是對lua的寫法有特殊要求,依賴bison且需要手動編譯。
如果只是使用簡單的Lua 語法檢查,則可以使用lua自帶的luac工具,命令如下:
如果要對lua進行打包操作,則使用如下命令:
如果需要使用各種網絡庫,可以使用luarocks , 使用方法類似於python 的pip/ez-install。
長按關注黑斑馬微信公眾號
歡迎訪問「百納遊戲團隊」技術博客:http://blog.dolphin-game.com