C/C++程式除錯和記憶體檢測
程式出現錯誤很正常,一個優秀的程式設計師必須學會除錯,發現錯誤並改正。減少程式錯誤最有效的方法是:在敲程式碼之前,多花點時間思考,如何構造程式,資料結構和演算法,儘量把細節提前寫下來,可以嘗試著在紙上寫出核心程式碼,這樣可以減少今後修改程式碼的時間。
1、常用的除錯技巧
(1)程式碼檢查,重新閱讀程式,排除比較明顯的錯誤。編譯時帶上 -Wall引數,生成所有的警告資訊。
gcc -Wall -pedantic -ansi 表示以ansi/iso生成所有的警告西資訊。
(2)取樣法: 在程式中增加一些程式碼,收集更多與程式執行時的行為相關的資訊。使用條件編譯,可以清楚的辨別哪些是除錯程式碼,有利於除錯後的程式碼整理。
例如:
#
ifdef
DEBUG
std
::
cout
<< x :
#
endif
程式編譯時可以選擇性的加上-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 安裝。
#
include
<iostream>
int
main
()
{
int
*ptr =
new
int
[
3
];
ptr[
3
]=
1
;
delete
[] ptr;
std
::
cout
<< ptr[
1
];
return
;
}
上面簡單的程式碼編譯執行不會發生錯誤,但是實際上發生了很嚴重的記憶體問題。ptr[3]訪問越界,std::cout <<ptr[i],讀已經釋放過的記憶體。
透過valgrind工具可以檢查出來:
[xgwang@localhost Desktop]$ g++ -g -o test2 test2.cpp
[xgwang@localhost 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)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31554652/viewspace-2638754/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++ 程式記憶體洩漏檢測方法C++記憶體
- C/C++記憶體洩漏及檢測C++記憶體
- 「EA 如何做記憶體和 C++ 除錯的」實錄記憶體C++除錯
- C程式記憶體洩露檢測工具——ValgrindC程式記憶體洩露
- 使用Microsoft Visual C++來檢測和隔離記憶體洩漏 (轉)ROSC++記憶體
- C/C++應用程式記憶體洩漏檢查統計方案C++記憶體
- [C++]記憶體分配C++記憶體
- C++記憶體管理C++記憶體
- 使用gdb和gdbserver除錯Android C/C++程式Server除錯AndroidC++
- C++記憶體管理:new / delete 和 cookieC++記憶體deleteCookie
- 請描述C/C++程式的記憶體分割槽?C++記憶體
- C++記憶體管理剖析C++記憶體
- C++ 記憶體對齊C++記憶體
- c++ 記憶體 繼承C++記憶體繼承
- C++記憶體掃描C++記憶體
- linux c程式記憶體檢查器LinuxC程式記憶體
- C/C++ 程式反除錯的方法C++除錯
- C++記憶體洩露檢查的5個方法C++記憶體洩露
- 10.3 除錯事件轉存程式記憶體除錯事件記憶體
- 使用GDB命令列偵錯程式除錯C/C++程式命令列除錯C++
- C/C++——C和C++怎樣分配和釋放記憶體,區別是什麼?C++記憶體
- 記憶體管理與檢測記憶體
- Node除錯指南-記憶體篇除錯記憶體
- 記憶體洩漏除錯工具記憶體除錯
- C++手寫記憶體池C++記憶體
- 控制C++的記憶體分配C++記憶體
- C++ 動態記憶體分配C++記憶體
- C++中“記憶體重疊”C++記憶體
- 轉載——C++記憶體管理C++記憶體
- C++動態記憶體分配C++記憶體
- SQL Server表駐留記憶體和檢測SQLServer記憶體
- C++ 共享記憶體ShellCode跨程式傳輸C++記憶體
- Visual C++ 2010 啟動記憶體洩漏檢測功能,VLD 記憶體洩漏檢查 都超簡單(2)C++記憶體
- C和C++的動態記憶體管理的區別C++記憶體
- 檢視程式cpu和記憶體佔用率記憶體
- C/C++記憶體對齊詳解C++記憶體
- C/C++記憶體分配以及釋放C++記憶體
- C/C++記憶體對齊原則C++記憶體