mcpField
V
valgrind

valgrind

github.com/mohitmishra786测试与质量269696 次安装18 周前更新
代码仓库

关于 valgrind

为 Agent 提供使用 Valgrind 检测内存错误及分析缓存、调用图和堆用量的指南,包含 Memcheck 报告解读、抑制规则和命令示例。

主要功能

  1. 01Memcheck 内存错误检测
  2. 02泄漏与未初始化值分析
  3. 03Cachegrind 缓存模拟
  4. 04Callgrind 调用图分析
  5. 05Massif 堆用量分析

适用场景

  1. 01排查内存泄漏或无效访问
  2. 02不使用 perf 时分析缓存行为
  3. 03查找调用开销与堆峰值位置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill valgrind

安装后在 Claude Code 中输入/valgrind确认已加载。

附带文件references/valgrind-vs-asan.md

详细介绍

Valgrind

用途

引导 Agent 使用 Valgrind 工具:使用 Memcheck 检测内存错误,使用 Cachegrind 模拟缓存,使用 Callgrind 生成调用图,并使用 Massif 分析堆内存。

触发条件

  • “我的程序有内存泄漏/释放后使用问题”
  • “我不能使用 ASan,可以改用 Valgrind 吗?”
  • “不使用 perf,如何分析缓存行为?”
  • “如何使用 Callgrind 可视化调用图?”
  • “如何分析堆内存分配模式?”
  • “Valgrind 报告了第三方代码中的错误,但我无法修复”

工作流

1. Memcheck — 内存错误检测

使用 -g -O1 编译以获得最佳结果。-O0 也可以;避免使用 -O2 或更高优化级别,否则可能产生误报。

valgrind --tool=memcheck \
         --leak-check=full \
         --show-leak-kinds=all \
         --track-origins=yes \
         --error-exitcode=1 \
         ./prog [args]

主要标志:

标志默认值作用
--leak-check=fullsummary显示完整的泄漏详情
--show-leak-kinds=alldefinite显示所有类型的泄漏
--track-origins=yesno显示未初始化值的来源(速度较慢)
--error-exitcode=N0如果发现错误,则以 N 退出(用于 CI 集成)
--log-file=filestderr将报告保存到文件
--suppressions=filenone忽略已知的误报
--gen-suppressions=yesno打印错误对应的抑制指令
--max-stackframe=N2000000为较深的调用栈增大限制
--malloc-fill=0xABoff填充已分配的内存(检测未初始化值的使用)
--free-fill=0xCDoff填充已释放的内存(检测释放后使用)
2. 理解 Memcheck 输出
==12345== Invalid read of size 4
==12345==    at 0x4007A2: foo (main.c:15)
==12345==    by 0x400846: main (main.c:30)
==12345==  Address 0x5204040 is 0 bytes after a block of size 40 alloc'd
==12345==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck.so)
==12345==    by 0x40074B: main (main.c:25)
  • 无效读取/写入:越界访问;检查数组边界
  • 使用未初始化的值:先读后写;使用 --track-origins=yes
  • 无效释放/重复释放:malloc/free 不匹配;检查所有权
  • 确定丢失:没有指针指向该内存块;属于明确的泄漏
  • 间接丢失:通过一连串内存块丢失;通常表示存在一个根泄漏
  • 可能丢失:指针可能指向内存块的中间位置;使用自定义分配器时通常是误报
3. 泄漏类型
类型含义
确定丢失没有指针指向该内存块
间接丢失通过另一个已丢失的内存块丢失
可能丢失指针指向内存块的中间位置
仍可访问程序退出时仍有指针指向该内存块;不算泄漏,但从未释放

对于库代码,使用 --show-leak-kinds=definite,indirect 可以减少仍可访问内存造成的干扰。

4. 抑制规则
# Generate suppression for current error
valgrind --gen-suppressions=yes ./prog 2>&1 | grep -A20 '{'

# Example suppression file (valgrind.supp)
{
   openssl_uninit
   Memcheck:Cond
   fun:SHA256_Init
   ...
}

# Use suppression file
valgrind --suppressions=valgrind.supp ./prog
5. Cachegrind — 缓存模拟
valgrind --tool=cachegrind ./prog

# Output: cachegrind.out.PID
# Annotate source
cg_annotate cachegrind.out.12345 --auto=yes

# Diff two runs
cg_diff cachegrind.out.before cachegrind.out.after

主要指标:

  • I1mr / ILmr:L1/末级指令缓存未命中率
  • D1mr / DLmr:L1/末级数据读取未命中率
  • D1mw / DLmw:L1/末级数据写入未命中率
6. Callgrind — 调用图分析
valgrind --tool=callgrind --callgrind-out-file=callgrind.out ./prog

# Analyse
callgrind_annotate callgrind.out

# Visualise in KCachegrind (GUI)
kcachegrind callgrind.out

Callgrind 的运行速度比 perf 慢,但无需 root 权限,并且能提供精确的调用次数。

7. Massif — 堆内存分析
valgrind --tool=massif ./prog

# Visualise
ms_print massif.out.PID | less

# GUI
massif-visualizer massif.out.PID

Massif 会显示堆内存用量随时间的变化;可用于查找内存分配峰值位置并追踪逐渐累积的泄漏。

8. 性能注意事项

Valgrind Memcheck 的运行速度约为原生程序的 1/10 至 1/50。可通过以下方式缓解:

  • 使用较短且具有代表性的工作负载
  • 使用 --error-exitcode=1,在 CI 中发现错误后立即失败
  • 在开发过程中使用 ASan(-fsanitize=address)进行更快的内存检查
  • 仅在无法使用 ASan 时(例如旧工具链或类似生产环境)使用 Valgrind

Valgrind 与 ASan 的比较请参阅 references/valgrind-vs-asan.md。

相关技能

  • 使用 skills/runtimes/sanitizers 获取更快的 ASan/UBSan 替代方案
  • 使用 skills/profilers/linux-perf 进行 CPU 级分析(速度比 Cachegrind 快)
  • 使用 skills/profilers/flamegraphs 可视化 Callgrind 输出

评论

支持 Markdown