程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 如何使用Valgrind memcheck工具進行C/C++的內存洩漏檢測

如何使用Valgrind memcheck工具進行C/C++的內存洩漏檢測

編輯:關於C++

系統編程中一個重要的方面就是有效地處理與內存相關的問題。你的工作越接近系統,你就需要面對越多的內存問題。有時這些問題非常瑣碎,而更多時候它會演變成一個調試內存問題的惡夢。所以,在實踐中會用到很多工具來調試內存問題。

 

Valgrind是運行在Linux上一套基於仿真技術的程序調試和分析工具,它包含一個內核——一個軟件合成的CPU,和一系列的小工具,每個工具都可以完成一項任務──調試,分析,或測試等。Valgrind可以檢測內存洩漏和內存違例,還可以分析cache的使用等,靈活輕巧而又強大,能直穿程序錯誤的心髒,真可謂是程序員的瑞士軍刀。

 

Valgrind工具包包含多個工具:

 

Memcheck是一個內存錯誤檢測器。它有助於使你的程序,尤其是那些用C和C++寫的程序,更加准確。Cachegrind是一個緩存和分支預測分析器。它有助於使你的程序運行更快。Callgrind是一個調用圖緩存生成分析器。它與Cachegrind的功能有重疊,但也收集Cachegrind不收集的一些信息Helgrind是一個線程錯誤檢測器。它有助於使你的多線程程序更加准確。DRD也是一個線程錯誤檢測器。它和Helgrind相似,但使用不同的分析技術,所以可能找到不同的問題。Massif是一個堆分析器。它有助於使你的程序使用更少的內存。DHAT是另一種不同的堆分析器。它有助於理解塊的生命期、塊的使用和布局的低效等問題。SGcheck是一個實驗工具,用來檢測堆和全局數組的溢出。它的功能和Memcheck互補:SGcheck找到Memcheck無法找到的問題,反之亦然。BBV是個實驗性質的SimPoint基本塊矢量生成器。它對於進行計算機架構的研究和開發很有用處。

 

這裡給大家介紹如何使用Valgrind memcheck工具進行C/C++的內存洩漏檢測。memcheck工具主要檢查下面的程序錯誤:

 

使用未初始化的內存 (Use of uninitialised memory)使用已經釋放了的內存 (Reading/writingmemory after it has been free’d)使用超過 malloc分配的內存空間(Reading/writing off the end of malloc’d blocks)對堆棧的非法訪問 (Reading/writinginappropriate areas on the stack)申請的空間是否有釋放 (Memory leaks –where pointers to malloc’d blocks are lost forever)malloc/free/new/delete申請和釋放內存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])src和dst的重疊(Overlapping src and dst pointers in memcpy() and related functions)
這幾個工具的使用是通過命令:valgrand --tool=name 程序名來分別調用的,當不指定tool參數時默認是 --tool=memcheck 。


使用前,需要保證valgrind已經安裝:/

使用 valgrind memcheck 方式:
/
編譯代碼時,加上調試參數 -g (用來在memcheck的輸出中生成行號,如果出現錯誤,可以定位到錯誤出現的位置)--leak-check=full 指的是完全檢查內存洩漏
a.out 為需要檢查的可執行程序

1. 使用未初始化的內存

#include 
#include 
 
int main(void)
{
    char *p;
 
    char c = *p;  //使用未初始化的內存
 
    printf(
 [%c]
,c);
 
    return 0;
}

在上面的代碼中,我們嘗試使用未初始化的指針“p”,讓我們運行 Memcheck 來檢查結果:
/

2. 在內存被釋放後進行讀/寫

#include 
#include 
 
int main(void)
{
    char *p = malloc(1);
    *p = 'a';
 
    char c = *p;
 
    printf(
 [%c]
,c);
 
    free(p);
    c = *p;//在內存被釋放後進行讀/寫
    
    return 0;
}

調試結果如下:/

3. 從已分配內存塊的尾部進行讀/寫

#include 
#include 
 
int main(void)
{
    char *p = malloc(1);
    *p = 'a';
 
    char c = *(p+1); //從已分配內存塊的尾部進行讀/寫
 
    printf(
 [%c]
,c);
 
    free(p);
    return 0;
}

調試結果如下:/

4. 內存洩露

#include 
#include 

//在這次的代碼中, 我們申請了一個字節但是沒有將它釋放
int main(void)
{
    char *p = malloc(1);
    *p = 'a';
 
    char c = *p;
 
    printf(
 [%c]
,c);
 
    return 0;
}

調試結果如下:/

5. 不匹配地使用malloc/new/new[] 和 free/delete/delete[]

#include 
#include 
#include
 
int main(void)
{
    char *p = (char*)malloc(1);
    *p = 'a';
 
    char c = *p;
 
    printf(
 [%c]
,c);
    delete p;
    return 0;
}

上面的代碼中,我們使用了malloc()來分配內存,但是使用了delete操作符來刪除內存。
注意: 使用g++來編譯上面的代碼,因為delete操作符是在C++中引進的,而要編譯C++需要使用g++。

 

調試結果如下:

/

 

6. 兩次釋放內存

 

#include 
#include 
 
int main(void)
{
    char *p = (char*)malloc(1);
    *p = 'a';
 
    char c = *p;
    printf(
 [%c]
,c);
    free(p);
    free(p);
    return 0;
}

調試結果如下:

 

/

 

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved