1 介绍
Massif是一个堆分析器,能够测量程序使用了多少堆内存。
Massif将程序堆的快照保存起来(生成massif.out文件),然后使用Massif-Visualizer进行可视化分析。
2 安装
sudo apt install massif-visualizer3 Valgrind massif 使用方法
参数示例:
valgrind -v --tool=massif \
--time-unit=B \
--detailed-freq=1 \
--massif-out-file=/path_to/massif.out \
./(path to)/test-demo <+ arg1 arg2 ... argn>参数解释:
-v:启用详细输出模式
--tool:指定使用massif工具
--time-uint:设置时间单位为Bytes
--detailed-freq:设置详细快照的频率为1,意味着每次内存分配都会生成详细的快照
--massif-out-file:设置输出文件的名称
./(path to)/test-demo:要分析的目标程序
可视化工具:
massif-visualizer /path_to/massif.out4 使用示例
测试代码:
#include <stdlib.h>
/**
* 分配指定字节数的内存块
* @param size 需要分配的字节数
* @return 成功时返回指向分配内存的指针;失败时返回 NULL
*/
void* create(unsigned int size) {
return malloc(size);
}
/**
* 分配并立即释放一块内存
* 用于演示“分配即释放”的场景,但注意:create() 返回的指针未被使用,
* 如果 create() 内部有额外资源初始化,则可能造成资源泄漏。
* @param size 需要分配并释放的字节数
*/
void create_destory(unsigned int size) {
void* p = create(size); // 分配内存
free(p); // 立即释放
}
int main(void) {
const int loop = 4; // 循环次数
char* a[loop]; // 用于保存 malloc 得到的指针,以便后续统一释放
unsigned int kilo = 1024; // 1 KB = 1024 字节
/* ----------- 第一阶段:循环分配内存 ----------- */
for (int i = 0; i < loop; i++) {
/* 1. 调用自定义 create() 分配 10 KB,但返回值被丢弃,造成内存泄漏 */
const unsigned int create_size = 10 * kilo;
create(create_size); // 内存泄漏:未保存指针,后续无法 free
/* 2. 使用标准 malloc 再分配 10 KB,并把地址保存到数组 a[i] */
const unsigned int malloc_size = 10 * kilo;
a[i] = malloc(malloc_size);
/* 3. 调用 create_destory():内部先 create 100 KB,再立即 free */
const unsigned int create_destory_size = 100 * kilo;
create_destory(create_destory_size);
}
/* ----------- 第二阶段:释放 malloc 得到的内存 ----------- */
for (int i = 0; i < loop; i++) {
free(a[i]); // 释放第一阶段 malloc 得到的内存
}
/* 注意:第一阶段 create() 分配的内存未释放,造成内存泄漏 */
return 0;
}编译指令:
gcc -g test-demo.c -o test-demo检测程序:
valgrind -v --tool=massif --time-unit=B --detailed-freq=1 --massif-out-file=massif.out ./test-demo可视化:
massif-visualizer ./massif.out
随着对内存分配的推进,可以清晰地看到任意时候的未释放的堆内存大小。到最后还有40kB,说明程序结束时,有40kB的内存没有被正常释放,也就意味着发生了内存泄露。
评论区