目 录CONTENT

文章目录

内存分析工具 Valgrind(memcheck)

TalentQ
2025-08-28 / 0 评论 / 0 点赞 / 6 阅读 / 0 字

1 Valgrind 简介

Valgrind 是一个用于内存调试、内存泄露检测和性能分析的工具,主要用于Linux平台,可以帮助开发者检测 C/C++程序中的各种内存错误:

  • 内存泄露(Memory Leak)

  • 访问未分配的内存(Invalid Memory Access)

  • 访问已经释放的内存(Use After Free)

  • 数组越界(Array Overrun)

  • 使用未初始化的内存(Uninitialized Memory)

Valgrind将内存泄漏分为4类:

  1. 明确泄漏(definitely lost):内存还没释放,但已经没有指针指向内存,内存已经不可访问。

  2. 间接泄漏(indirectly lost):泄漏的内存指针保存在明确泄漏的内存中。由于明确泄漏的内存不可访问,间接泄漏的内存也不可访问。

  3. 可能泄漏(possibly lost):指针并不指向内存头地址,而是指向内存内部的位置。

  4. 仍可访达(still reachable):指针一直存在且指向内存头部,直至程序退出时内存还没释放。

2 安装

valgrind是一个linux命令行工具,直接安装即可。

sudo apt update
sudo apt install valgrind

用户手册:Valgrind User Manual

3 Valgrind memcheck 使用方法

Memcheck: a memory error detector.

参数示例:

valgrind --log-file=valgrind.log \
         --tool=memcheck \
         --leak-check=full \
         --show-reachable=yes (equal to `--show-leak-kinds=all`) \
         --leak-resolution=low \
         ./test-app arg1 arg2 

参数解释:

  • --log-file:指定valgrind日志保存位置

  • --tool:指定使用memcheck工具

  • --leak-check:指定如何报告内存泄漏

    • no:没有输出

    • summary:只输出统计的结果

    • full:输出详细内容

  • --show-reachable:--show-reachable=yes等效于--show-leak-kinds=all,显示所有内存泄漏类型

  • --leak-resolution:-leak-resolution=low,日志中合并相似的泄漏记录

3.1 检测内存泄露

测试代码:

#include <stdlib.h>

int main(int argc, const char *argv[]) {
  int *array = malloc(sizeof(int));  // 申请了内存,但没有释放
  return 0;
}

编译指令:

gcc -g test-demo.c -o test-demo

检测程序:

valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-reachable=yes --leak-resolution=low ./test-demo

输出:

日志分析:

  • HEAP SUMMARY 表示堆上内存分配的情况,1 allocs表示分配了1次内存,0 frees表示没有释放内存;

  • 提示用户程序出现了明确泄漏(definitely lost),代码位置 main (test-demo.c:4);

3.2 检测内存间接丢失

测试代码:

#include <stdio.h>
#include <stdlib.h>

struct list {
  int value;
  struct list *next;
};

int main(int argc, const char *argv[]) {
  struct list *root;

  root = (struct list *)malloc(sizeof(struct list));
  root->next = (struct list *)malloc(sizeof(struct list));
  printf("root: %p, roop->next: %p\n", root, root->next);
  root = NULL;  // 丢失root指针,导致root存储的next指针成为了间接泄漏
  return 0;
}

编译指令:

gcc -g test-demo.c -o test-demo

检测程序:

valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-reachable=yes --leak-resolution=low ./test-demo

输出:

日志分析:

  • HEAP SUMMARY 表示堆上内存分配的情况,3 allocs表示分配了3次内存,1 frees表示释放了1次内存

  • 提示用户程序出现了间接泄漏(indirectly lost),代码位置 main (test-demo.c:13)

  • 提示用户程序出现了明确泄漏(definitely lost),代码位置 main (test-demo.c:12)

3.3 检测内存越界访问

测试代码:

#include <iostream>
#include <vector>

int main(int argc, const char *argv[]) {
  std::vector<int> v(10, 0);
  std::cout << v[10] << std::endl;
  return 0;
}

编译指令:

g++ -g test-demo.cc -o test-demo

检测程序:

valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-reachable=yes --leak-resolution=low ./test-demo

输出:

日志分析:

  • Invalid read of size 表示内存越界访问,代码位置 main (test-demo.cc:6)

0

评论区