内存泄漏调试工具

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和堆内存性能分析工具,帮助发现性能瓶颈。较低的性能开销,可用于生产环境的性能监控。 主要用于性能分析。 性能优化和瓶颈分析。生产环境下的性能监控。
posted on 2024-03-17 22:51  未连接到互联网  阅读(79)  评论(0编辑  收藏  举报