記憶體洩漏除錯工具

未连接到互联网發表於2024-03-17

asanvalgrindcoveritygpertools都是用於幫助開發人員發現和除錯程式碼中的各種問題的工具,但它們在特定方面有著不同的重點和功能。

ASan (AddressSanitizer):

ASan 常用於 C/C++ 程式碼的靜態和動態記憶體訪問錯誤檢測,透過在編譯時注入額外的程式碼來對記憶體進行訪問監控,包括緩衝區溢位、使用已釋放記憶體、記憶體洩漏等問題。

#include <stdio.h>

int main() {
    int buffer[5];
    for (int i = 0; i <= 5; i++) {  // 訪問陣列越界
        buffer[i] = i;
    }
    return 0;
}

編譯以上程式時使用 ASan 進行記憶體錯誤檢測:

$ gcc -fsanitize=address -o program program.c

程式執行時將會報告記憶體訪問錯誤:

$ ./program
=================================================================
==1==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc8fdaedf0 at pc 0x400534 bp 0x7ffc8fdaed60 sp 0x7ffc8fdaed58
READ of size 4 at 0x7ffc8fdaedf0 thread T0
    #0 0x400533 in main program.c:5

Valgrind:

Valgrind是一款用於記憶體錯誤檢測、記憶體洩漏檢測和效能分析的工具套件,其中最為人熟知的是Memcheck工具。Memcheck可以檢測到類似ASan的問題,包括記憶體越界訪問、使用未初始化的記憶體、記憶體洩漏等。除了記憶體工具外,Valgrind還包括其他工具,如Cachegrind用於快取分析,Callgrind用於函式呼叫分析等。

#include <stdlib.h>

int main() {
    int* ptr = malloc(sizeof(int));
    *ptr = 5;
    free(ptr);
    int val = *ptr;  // 使用已釋放的記憶體
    return 0;
}

使用 Valgrind 時不需要額外的編譯選項:

$ gcc -o program program.c

編譯成功後用 Memcheck 工具進行記憶體錯誤檢測:

$ valgrind --tool=memcheck ./program
==1==ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==1==ERRORS SUMMARY:
==1==Invalid read of size 4
==1==    at 0x400527: main (program.c:7)
==1==  Address 0x5204040 is 0 bytes inside a block of size 4 free'd
==1==    at 0x4C33A10: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

Coverity:

Coverity是一款靜態程式碼分析工具,主要用於檢測程式碼中的潛在缺陷、安全漏洞和可靠性問題。Coverity可以在編譯階段對程式碼進行靜態分析,發現例如空指標解引用、資源洩漏、併發問題等各種型別的缺陷。

在專案目錄下執行 Coverity 靜態分析工具,Coverity 將對程式碼進行靜態分析,並生成問題報告:

$ cov-analyze --dir <project_directory> --enable-constraint-fpp --enable-virtual --enable-exception --enable-exception-destructor --enable-callgraph-metrics

Gperftools:

Gperftools是Google開發的一套效能分析工具,包括CPU Profiler(CPU效能分析)和Heap Profiler(堆記憶體分析)等工具。CPU Profiler可用於檢視程式中CPU時間消耗的情況,幫助找到效能瓶頸。Heap Profiler則可以用於檢視記憶體分配和釋放的情況,幫助發現記憶體洩漏等問題。

#include <stdio.h>

void busyFunction() {
    for (int i = 0; i < 1000000; i++) {
        printf("Doing some work...\n");
    }
}

void functionWithBottleneck() {
    // 模擬存在效能瓶頸的函式
    busyFunction();
}

int main() {
    functionWithBottleneck();
    return 0;
}

編譯以上程式時連結 Gperftools 的 CPU Profiler 庫,執行程式時啟動 CPU Profiler:

$ gcc -o program program.c -lprofiler
$ CPUPROFILE=profile.prof ./program

檢視效能分析報告:

$ pprof --text ./program profile.prof

對比

工具 優勢 劣勢 適用場景
ASan 實時執行時檢測記憶體訪問錯誤,能夠快速發現問題並提供詳細報告。較低的效能開銷,適用於除錯和開發階段的快速問題定位。 只能檢測到記憶體相關的問題,不支援靜態程式碼分析。在某些情況下可能會影響程式的效能。 快速定位記憶體訪問錯誤和洩漏問題、開發階段的除錯和問題排查。
Valgrind 提供多種工具,包括記憶體檢測、效能分析等,功能豐富。能夠檢測到更多型別的記憶體錯誤和洩漏。 執行時效能開銷較大,可能影響程式執行速度。不能檢測到所有的靜態程式碼缺陷。 複雜程式中的記憶體錯誤和洩漏問題檢測。效能分析和最佳化。
Coverity 靜態程式碼分析,可以在編譯階段發現潛在問題。提供詳細的問題報告和分類,幫助開發人員理解和解決問題。 可能存在誤報情況,需要人工確認問題。對於大型專案,分析時間較長。 大型專案的缺陷檢測和安全漏洞分析。程式碼審查和質量保證。
Gperftools 提供CPU和堆記憶體效能分析工具,幫助發現效能瓶頸。較低的效能開銷,可用於生產環境的效能監控。 主要用於效能分析。 效能最佳化和瓶頸分析。生產環境下的效能監控。

相關文章