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 的现代替代品

相关推荐
风曦Kisaki5 分钟前
# Linux 磁盘查看命令详解:df 与 du
linux·运维·网络
路溪非溪8 分钟前
Linux中gpio子系统的现代接口
linux·arm开发·驱动开发
攻城狮在此11 分钟前
华为交换机Console口密码如何清除
运维·网络·华为
内心的一片海1 小时前
服务器内存异常占用
运维·服务器
文静小土豆1 小时前
Centos7负载异常过高排查思路(Load Average)
linux
Deitymoon1 小时前
linux——原子操作
linux
liulilittle2 小时前
C++ 无锁编程:单停多发送场景高性能方案
服务器·开发语言·c++·高性能·无锁·原子
m0_738120722 小时前
渗透基础知识ctfshow——Web应用安全与防护(第一章)
服务器·前端·javascript·安全·web安全·网络安全
亚空间仓鼠2 小时前
OpenEuler系统常用服务(四)
linux·运维·服务器·网络
郝学胜-神的一滴2 小时前
Socket实战:从单端聊天到多用户连接的实现秘籍
服务器·开发语言·python·网络协议·pycharm