
程式出現錯誤很正常,一個優秀的程式員必須學會調試,發現錯誤并改正。減少程式錯誤最有效的方法是:在敲代碼之前,多花點時間思考,如何構造程式,資料結構和算法,盡量把細節提前寫下來,可以嘗試着在紙上寫出核心代碼,這樣可以減少今後修改代碼的時間。
1、常用的調試技巧
(1)代碼檢查,重新閱讀程式,排除比較明顯的錯誤。編譯時帶上
-Wall參數,生成所有的警告資訊。 gcc -Wall -pedantic -ansi 表示以ansi/iso生成所有的警告西資訊。 (2)取樣法:在程式中增加一些代碼,收集更多與程式運作時的行為相關的資訊。使用條件編譯,可以清楚的辨識哪些是調試代碼,有利于調試後的代碼整理。
例如:
程式編譯時可以選擇性的加上-DDEBUG。如果加上這個标志,就定義了DEBUG這個符号,進而在程式中包含調試用的額外代碼,沒有加上該标志,這些調試代碼将删除。
(3)程式的受控執行。用調試器來控制代碼的運作,随時檢視這些變量的狀态。為了能夠調試程式,需要在編譯和連結時為每個源檔案加上編譯選項參數。這些選項的作用是讓編譯器在程式中添加額外的調試資訊。這些資訊包括符号和源代碼行号,調試器将利用這些資訊向使用者顯示程式已經執行到的源代碼的位置。-g标志是對程式調試性編譯時常用的一個選項。調試資訊的加入使可執行程式的長度成倍的增長、容量增加,程式運作時的記憶體數量還是和原來一樣,程式調試結束後,最好還是将調試資訊從程式的發行版中删除。
2、使用gdb進行程式調試
常用功能指令:g++ -g -o test test.cpp //編譯時加上-g參數
1、啟動gdb: gdb test
2、help
3、具備帶有曆史記錄的指令行編輯功能,方向鍵選擇之前執行過的指令,直接Enter鍵再次執行最近執行過的那條指令。單步調試非常有用。
4、quit:退出
5、run:執行這個程式,程式運作失敗時gdb會報告失敗的原因和位置。
6、backtrace(bt):棧跟蹤,失敗時停止的位置,幫助我們找到程式到達錯誤地點的路徑。
7、print:run 後檢查變量,注意變量的生命期。
8、列印圍繞目前位置前後的一段代碼,繼續使用list可以顯示更多的代碼。
9、設定斷點,停止程式的運作,檢視變量。help breakpoint,break lineNumber,cont,end,display,disable breakpoint number,clear,commands breakpointNumber.
10、設定斷點後經常使用單步調試指令next(n),檢視程式運作的細節。
3、valgrind記憶體調試
動态記憶體配置設定很容易出現程式漏洞,必須清楚自己配置設定的每一塊記憶體,而且要确定沒有使用已經釋放的記憶體塊,非常重要。記憶體調試的工具有很多,這裡使用的是valgrind工具。在centos 7中直接使用 yum install valgrind 安裝。
上面簡單的代碼編譯運作不會發生錯誤,但是實際上發生了很嚴重的記憶體問題。ptr[3]通路越界,std::cout <<ptr[i],讀已經釋放過的記憶體。
通過valgrind工具可以檢查出來:[[email protected] Desktop]$ g++ -g -o test2 test2.cpp
[[email protected] Desktop]$ valgrind ./test2
==21739== Memcheck, a memory error detector
==21739== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21739== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==21739== Command: ./test2
==21739==
==21739== Invalid write of size 4
==21739== at 0x40081E: main (test2.cpp:8)
==21739== Address 0x5a1504c is 0 bytes after a block of size 12 alloc'd
==21739== at 0x4C2A7AA: operator new[](unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==21739== by 0x400811: main (test2.cpp:7)
==21739==
==21739== Invalid read of size 4
==21739== at 0x40083F: main (test2.cpp:11)
==21739== Address 0x5a15044 is 4 bytes inside a block of size 12 free'd
==21739== at 0x4C2B5E1: operator delete[](void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==21739== by 0x400836: main (test2.cpp:10)
==21739==
0==21739==
==21739== HEAP SUMMARY:
==21739== in use at exit: 0 bytes in 0 blocks
==21739== total heap usage: 1 allocs, 1 frees, 12 bytes allocated
==21739==
==21739== All heap blocks were freed -- no leaks are possible
==21739==
==21739== For counts of detected and suppressed errors, rerun with: -v
==21739== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)