当前位置: 首页 > news >正文

程序持续内存泄漏问题定位参考

0 概括

本文用于记录 x86-Linux 应用程序发生持续性内存泄漏问题时的定位方法。主要介绍valgrind工具的应用。

1 原理

对于内存泄漏问题的定位,一种朴素的想法就是对内存申请点进行监控。对于一个内存申请调用点(例如c/c++中的malloc函数),记录下该调用点被触发时的调用栈 c a l l s t a c k callstack callstack,以及申请到的内存 m e m o r y memory memory。同一个调用栈可能申请多次内存,我们把申请到的内存都记录下来,于是我们得到了一个统计表,表中元素长这样: ( c a l l s t a c k i , { m e m o r y i 1 , m e m o r y i 2 , . . . } ) (callstack_i,\{memory_{i}^{1},memory_{i}^{2},...\}) (callstacki,{memoryi1,memoryi2,...})。当 m e m o r y i j memory_{i}^{j} memoryij内存被释放(例如c/c++中的free函数),则把统计表中的 m e m o r y i j memory_{i}^{j} memoryij项删除即可。如此一来,当程序结束,依旧持有 m e m o r y memory memory的那些 c a l l s t a c k callstack callstack就可以认为是潜在的内存泄漏点。

上述的朴素想法,ASAN工具已经帮我们实现。本文讨论更特殊的场景,对ASAN工具的使用不再赘述。在程序持续运行,持续内存泄漏的场景中,我们需要对上述朴素想法做一点点改变。在 t i m e s t a m p timestamp timestamp时刻,我们记录一下该时刻的统计表 ( c a l l s t a c k i , { m e m o r y i 1 , m e m o r y i 2 , . . . } ) (callstack_i,\{memory_{i}^{1},memory_{i}^{2},...\}) (callstacki,{memoryi1,memoryi2,...})。随程序的运行,我们便得到了一张随时间变化的统计表 [ t i m e s t a m p , { ( c a l l s t a c k i , { m e m o r y i 1 , m e m o r y i 2 , . . . } } ) ] [timestamp, \{(callstack_i,\{memory_{i}^{1},memory_{i}^{2},...\}\})] [timestamp,{(callstacki,{memoryi1,memoryi2,...}})]。某一时刻的统计表我们称之为一个内存切片。如此一来,当我们观测到一个 c a l l s t a c k i callstack_i callstacki的内存持有量随时间不断增加,则可以识别该点为潜在的内存泄漏点。这种内存切片的想法,valgrind工具已经帮我们实现。

2 valgrind工具的使用

本文不详细介绍valgrind工具,只通过简单案例介绍如何使用valgrind工具形成内存切片图。

x86-Linux服务器环境,先执行以下命令安装valgrind工具。

sudo apt install valgrind
sudo apt install massif-visualizer

再给出一个持续运行持续内存泄漏的简单范例main.cpp。

#include <thread>
#include <chrono>
#include <vector>
#include <string>

void sleepMs(int milliseconds) {
    std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}

int main(int /*argc*/, char** /*argv*/) {
    std::vecotr<std::string> vec;
    
    while(true) {
    	// 新增10个数据
	    for (size_t i = 0; i < 10U; i++) {
	    	vec.push_back(std::string(1000000, 'A'));
	    	sleepMs(100);
	    }
	    // 释放9个数据
	    for (size_t j = 0; j < 9U; j++) {
	    	vec.pop_back();
	    	sleepMs(100);
	    }
    }
    return 0;
}    

对应的编译命令为g++ -g -o exe main.cpp
在这里插入图片描述

接下来使用valgrind运行这个程序,生成内存切片。对应的命令为

valgrind --tool=massif --time-unit=B ./exe

运行一段时间后,ctrl+c结束程序,就生成了对应的内存切片文件massif.out.<pid>。使用可视化工具打开这个内存切片文件,效果如下。
在这里插入图片描述
可以看到调用点持有的内存量随时间的变化,还可以看到不同时刻,各调用栈持有的内存量。至此可以协助我们分析持续性的内存泄漏。

3 结论

本文记录持续内存泄漏问题的一种定位方法,记录valgrind工具的使用。但是valgrind工具会极大影响程序性能。对商用程序,如果设计得不好,性能受影响的情况下有可能功能都不正常。所以本文方法只是一种参考,具体情况还需要具体分析。

相关文章:

  • 关于异步消息队列的详细解析,涵盖JMS模式对比、常用组件分析、Spring Boot集成示例及总结
  • Java面试黄金宝典46
  • Web前端性能指标Web3D性能优化
  • 【海奇hcrots】
  • Vue3.5 + Vite6.x 项目的完整 Stylelint 配置方案,支持 .vue/.html 内联样式、Less/SCSS/CSS 等多种文件类
  • Linux上通过Docker部署Zabbix6.2监控平台
  • 2.3 Spark运行架构与流程
  • hive/doris查询表的创建和更新时间
  • 【“星睿O6”评测】三套OpenCV,OpenCL/KleidiCV/JPG硬件编码加速测试
  • Python 中使用单例模式
  • vim 编辑器 使用教程
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(1):承上启下,继续上路
  • 突破焊丝虚影干扰,端子焊点缺陷检测如何实现自动化?
  • 基于 SpringBoot 的校园论坛系统
  • 蓝牙连接hci 命令和事件的交互
  • OpenSceneGraph相机系统
  • 求x的c(n,m)次方
  • 智慧零售新引擎!数图将亮相CHINASHOP 2025,助力企业降本增效
  • MCP基础学习二:MCP服务搭建与配置
  • repo仓库文件清理
  • 站内优化网站怎么做/免费发布推广信息的平台
  • 专业做网站的企业/百度关键词搜索趋势
  • 上海seo网站优化软件/关键词抓取工具都有哪些
  • 制作好的网站必须申请/运营推广公司
  • 行业门户网站cms/百度问答seo
  • 专业做二手网站/seo推广思路