Linux 性能实战系列 - 附录 Valgrind介绍

Valgrind 是一个 动态二进制分析框架 ,本身像一个"平台",在它之上运行不同的 分析工具(tools)

其中最常用的三个工具就是:

  • Memcheck
  • Callgrind
  • Massif

它们的关系可以理解为:

复制代码
                Valgrind (框架)
                      │
     ┌────────────────┼────────────────┐
     │                │                │
  Memcheck         Callgrind         Massif
 (内存正确性)      (CPU性能分析)     (堆内存分析)

三者目标完全不同,只是运行在同一个框架上。


一、Memcheck:内存错误检测工具

Memcheck 是 Valgrind 最常用的工具 ,主要用于发现 内存使用错误

能检测的问题

1️⃣ 内存泄漏

复制代码
definitely lost: 1024 bytes

例如:

c 复制代码
char *p = malloc(100);

没有 free(p)


2️⃣ 未初始化内存使用

c 复制代码
int x;
printf("%d\n", x);

Memcheck 会报告:

复制代码
Conditional jump or move depends on uninitialised value

3️⃣ 越界访问

c 复制代码
int a[10];
a[10] = 5;

报告:

复制代码
Invalid write of size 4

4️⃣ Use-after-free

c 复制代码
free(p);
*p = 1;

原理(简化)

Memcheck 为程序维护两种 shadow memory:

复制代码
真实内存
   │
   ▼
shadow memory
 ├── addressability (是否可访问)
 └── definedness   (是否初始化)

每条指令都会被 动态插桩(instrumentation) 检查。


运行方式

bash 复制代码
valgrind --tool=memcheck ./app

二、Callgrind:CPU性能分析工具

Callgrind 用于 分析程序执行时 CPU 时间消耗在哪里

它记录:

  • 函数调用关系
  • 每个函数执行的指令数
  • 调用图

输出文件:

复制代码
callgrind.out.<pid>

可用工具可视化:

  • KCachegrind
  • QCachegrind

示例

bash 复制代码
valgrind --tool=callgrind ./app

结果:

复制代码
Function                 Instructions
--------------------------------------
main                     10,000
foo                      6,000
bar                      3,000

可视化调用关系:

复制代码
main
 ├── foo
 │     └── baz
 └── bar

特点

Callgrind 不测真实时间,而是统计:

复制代码
CPU instructions

所以适合:

  • 算法性能分析
  • 热点函数定位

三、Massif:堆内存使用分析

Massif 用于分析:

程序在运行过程中堆内存是如何增长的

也就是 memory profile


运行

bash 复制代码
valgrind --tool=massif ./app

输出:

复制代码
massif.out.<pid>

分析:

bash 复制代码
ms_print massif.out.<pid>

示例输出

复制代码
Heap usage

    MB
10.0|        ######
    |       #      #
 5.0|      #        #
    |     #          #
 0.0+----+----+----+---->
      t1   t2   t3   t4

表示:

复制代码
时间  → 内存变化

Massif 会告诉你

复制代码
Peak heap: 120MB

90MB allocated at:
   foo()
   bar()
   main()

也就是:

哪一段代码造成了最大内存占用


四、三者核心区别

工具 作用 分析对象 典型用途
Memcheck 内存错误检测 内存访问 查内存泄漏
Callgrind CPU性能分析 指令执行 找热点函数
Massif 堆内存分析 内存占用 分析内存增长

五、三者运行开销对比

Valgrind 最大问题是

工具 速度
Memcheck 20--50x 慢
Callgrind 10--30x 慢
Massif 5--20x 慢

原因:

Valgrind 会:

复制代码
CPU指令
 ↓
Valgrind IR
 ↓
插桩
 ↓
执行

属于 动态二进制翻译 (DBI)


六、一个完整调试流程(真实开发常见)

一个 C/C++ 项目常见的 Valgrind 使用流程:

第一步:找内存问题

复制代码
valgrind --tool=memcheck

解决:

  • memory leak
  • invalid read/write

第二步:分析性能热点

复制代码
valgrind --tool=callgrind

定位:

复制代码
最慢函数

第三步:分析内存峰值

复制代码
valgrind --tool=massif

定位:

复制代码
内存增长来源

七、三者在 Valgrind 内部的关系(架构)

Valgrind 架构:

复制代码
                Program
                   │
                   ▼
           Valgrind Core
     (Dynamic Binary Translation)
                   │
        ┌──────────┼──────────┐
        │          │          │
     Memcheck   Callgrind   Massif
   (memory)     (cpu)       (heap)

核心部分:

复制代码
VEX IR

所有工具都基于这个 IR 插桩。


八、一个很多人不知道的事实

很多人以为:

复制代码
Memcheck 可以分析内存占用

其实 不行

Memcheck 只做:

复制代码
memory correctness

而不是:

复制代码
memory profiling

所以:

需求 工具
查内存泄漏 Memcheck
查内存占用 Massif

九、一个非常实用的工具组合

Linux 内存分析常见组合:

工具 用途
Valgrind Memcheck 查错误
Valgrind Massif 查内存
perf 查 CPU
heaptrack 高级 heap profiler

其中:

Heaptrack

实际上是 Massif 的现代替代品

相关推荐
IPdodo_10 分钟前
静态 IP、住宅 IP 和固定出口有什么区别?开发场景选型指南
服务器·网络·网络协议·tcp/ip·代理ip
云原生指北41 分钟前
Docker Sandboxes 上手:从安装到第一次跑 Agent
运维·docker·容器
小马同学-1 小时前
高可用-Keepalived全解析
linux·运维
ziyun6668881 小时前
Docker 容器化 Web 服务架构搭建与自动化运维项目
运维·docker·架构
wavemap1 小时前
HyperPHP 免费主机无限流量
服务器·php
Forever Nore1 小时前
LeetCode 13 罗马数字转整数 - 按规则处理
linux·服务器·leetcode
我不会插花弄玉2 小时前
2.Linux基础指令下【由浅入深-Linux】
linux·服务器
梦想的旅途22 小时前
企微 API 二次开发:利用 AI Agent 实现自动化运维
运维·人工智能·企业微信
安科瑞-小李2 小时前
铁路智能运维进化路线:自动化→状态可视→预测维护
运维·自动化·数据采集·能耗可视化
雯宝3 小时前
3. 驱动框架(块设备)
linux