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

内存泄漏 定位方法

目录

内存概念

物理内存

虚拟内存

内存泄漏

定位方法和手段

1.MemInFo

MemTotal

MemFree

MemAvailable

Cached

2 vmalloc info

3.Kmemleak

算法原理

使用方法

参考文献与链接:


如果你点进这篇文章,那么要么你是一个C\C++程序员,要么你曾经或多或少被内存泄漏问题所困扰。嗯,作为一个Linux嵌入式程序员,我自然是两者兼具。

        在工作中,总是会遇到内存泄漏的问题,对于那些记性不太好的程序员,本人在此强烈建议如果你有手动分配内存的话,请一一记录,否则很多时候你的差记性,可能会对他人造成莫大的困扰。建议大家都能严格要求自己吧。

        好吧前面是一些牢骚呢,下面我们来正式地聊一聊,面对内存泄漏和内存碎片,我们到底有些什么手段去检测吧。当然,限于本人的水平,本文的所有方法,仅仅是本人在工作中遇到、学习到的,可能存在着很大的局限性。如果各位看官,有什么新的方法,或者比较特别的手段也能用来检测内存泄漏,希望也能一块分享一下,共同进步呢。

内存概念

要聊到内存泄漏与内存碎片问题, 那么我们就必须要先来讲一下内存这个概念。

内存分为:

  1. 物理内存

    物理内存:很好理解,物理内存就是硬件所提供的的内存大小
  2. 虚拟内存

    虚拟内存:每个进程在运行时使用到的,一般都是虚拟内存。在Linux系统下,系统一般允许进程获得4G的内存。0-1GB为内核空间,而1-4GB为用户态空间。

而我们在进程中所使用到的虚拟内存地址,看起来地址是连续的,但是实际上,相对于物理器件来说,我们所分配的虚拟内存地址都是通过一定的映射关系之后,将不连续的物理内存地址拼接起来,形成一段看起来连续的虚拟内存地址。

而IOMMU则是用来隔离物理内存与虚拟内存的,并且将他们进行关系映射的模块。

当然,这里面还涉及到了分页、页表、slab算法、buddy算法等一系列比较复杂的东西,但是由于不在本次的讨论范围内,那就还是下次再议吧。

总的来说,内存的概念可以比较简单地如上理解。

内存泄漏

        那么,什么是内存泄漏呢?

        简单地来说,就是当我们手动分配了内存(x_malloc等),却忘记手动释放内存(x_free),那么当这个程序被销毁或者退出时,这部分被手动分配的内存,并不会自动释放,返回给系统进行再次管理,而是会永久分配,但是却无人使用。当我们的程序不断地运行和退出时,就会造成无人使用的内存越来越多,从而导致内存被耗尽,出现各种各样的问题。

        所以,再次提醒,一定要记得手动释放掉自己分配的内存。求求各位了。

那么有什么手段去分析,某个程序到底是否存在内存泄漏呢?

定位方法和手段

1.MemInFo

我觉得在我们使用不同的手段去检测前,我们一定要了解Linux下,系统内存的状况。

通过如下命令,能看到Linux当前的内存状态

cat /proc/meminfo
(负责输出/proc/meminfo的源代码是:fs/proc/meminfo.c : meminfo_proc_show())
MemTotal:        3809036 kB
MemFree:          282012 kB
MemAvailable:     865620 kB
Buffers:               0 kB
Cached:           854972 kB
SwapCached:       130900 kB
Active:          1308168 kB
Inactive:        1758160 kB
Active(anon):    1010416 kB
Inactive(anon):  1370480 kB
Active(file):     297752 kB
Inactive(file):   387680 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       4063228 kB
SwapFree:        3357108 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:       2104412 kB
Mapped:            40988 kB
Shmem:            169540 kB
Slab:             225420 kB
SReclaimable:     134220 kB
SUnreclaim:        91200 kB
KernelStack:        5936 kB
PageTables:        35628 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     5967744 kB
Committed_AS:    5626436 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      351900 kB
VmallocChunk:   34359363652 kB
HardwareCorrupted:     0 kB
AnonHugePages:    139264 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      204484 kB
DirectMap2M:     3915776 kB

然后我们可以看到如上输出。

当然输出信息有很多,但是我们只需要关注部分比较重要的即可。

MemTotal

系统从加电开始到引导完成,firmware/BIOS要保留一些内存,kernel本身要占用一些内存,最后剩下可供kernel支配的内存就是MemTotal。这个值在系统运行期间一般是固定不变的。可参阅解读DMESG中的内存初始化信息。

MemFree

表示系统尚未使用的内存。[MemTotal-MemFree]就是已被用掉的内存。

MemAvailable

有些应用程序会根据系统的可用内存大小自动调整内存申请的多少,所以需要一个记录当前可用内存数量的统计值,MemFree并不适用,因为MemFree不能代表全部可用的内存,系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以这部分可回收的内存加上MemFree才是系统可用的内存,即MemAvailable。/proc/meminfo中的MemAvailable是内核使用特定的算法估算出来的,要注意这是一个估计值,并不精确。

Cached

程序运行的缓存,这部分内存属于是释放后,不会立即返还给系统。而是会作为cached内存,当程序再次访问内存时,会先查找cached内存(分L1 L2 L3),如果无法cache hint,就会出发缺页错误,从而进行新的内存访问。

echo 3 > /proc/sys/vm/drop_caches 

调用上面的命令,即可将所有的cached内存返还给MemFree上来。

当然,在我们考虑有多少cache可供回收的时候,首先要知道的是:不同版本的”free”命令计算cache值的算法不同,据不完全统计举例如下:

1、版本:procps-3.2.8-36

cache值等于/proc/meminfo中的”Cached”;

2、版本:procps-3.3.9-10.1

cache值等于/proc/meminfo的 [Cached + SReclaimable];

3、版本:procps-ng-3.3.10-3

cache值等于/proc/meminfo的 [Cached + Slab]。

所以,到这里,我们就有一个“古法”的手段去检测是否出现了内存泄漏。

也就是我们可以不断运行我们的程序,然后再去监测/proc/meminfo里的相关信息,如果当我们drop cache后,仍然存在着Memfree不断减少的情况,那么基本上可以确定是存在内存泄漏了。

2 vmalloc info

在/proc/meminfo中,我们最多只能大概确定,当前的程序运行是否存在内存泄漏的情况。但是当我们实际在开发的时候,由于涉及到很多模块。我们实际上并不能确定,内存泄漏到底是因为哪个模块引起的。

这个时候,我们有更加方便的proc信息可以查看。即

cat /proc/vmallocinfo

通过vmalloc分配的内存都统计在/proc/meminfo的 VmallocUsed 值中,但是要注意这个值不止包括了分配的物理内存,还统计了VM_IOREMAP、VM_MAP等操作的值,譬如VM_IOREMAP是把IO地址映射到内核空间、并未消耗物理内存,所以我们要把它们排除在外。从物理内存分配的角度,我们只关心VM_ALLOC操作,这可以从/proc/vmallocinfo中的vmalloc记录看到:

 

注:/proc/vmallocinfo中能看到vmalloc来自哪个调用者(caller),那是vmalloc()记录下来的,相应的源代码可见:mm/vmalloc.c: vmalloc > __vmalloc_node_flags > __vmalloc_node > __vmalloc_node_range > __get_vm_area_node > setup_vmalloc_vm

通过运行和销毁程序,我们就可以看到对应的内存的分配和释放情况。正常来说,程序运行时,我们会看到vmalloc记录了所有调用vmalloc的调用栈及其分配到的虚拟内存地址。

而当销毁时,这些内存都会被释放掉,而消失在proc中。

如果当我们运行并退出程序后,vmallocinfo中还存在着我们程序中的函数分配信息,那么基本上可以确认,就是这个函数所分配的内存没有释放。

3.Kmemleak

此外,也有很直接的工具可以进行内存泄漏的检测。

分别是kmemleak、valgrind\perf等

由于在我工作的环境中,没法用上valgrind、perf等工具,所以接触不深,加之网上已经有很多这些工具的博客,就不班门弄斧了。

主要说一下kmemleak吧。

Kmemleak主要是Linux提供的工具,可以通过内核编译选项进行打开。

但是其检测到的信息,可能并不是特别准确,他独特的检测算法,只能展示出有可能的内存泄漏,但也不一定就是。

算法原理

Kmemleak算法的原理简单地来说,就是将通过kmalloc\vmalloc\kmem_cache_alloc等一系列分配函数将其指针连同分配大小、堆栈跟踪等信息一块存储在红黑树中。并且会追踪对应的release函数,检测内存释放,并将其从红黑树中删除。

扫描算法步骤:

  1. 将所有对象标记为白色(剩余的白色对象稍后将被视为孤立对象)
  2. 从数据部分和堆栈开始扫描内存,根据存储在 rbtree 中的地址检查值。如果找到指向白色对象的指针,则将该对象添加到灰名单
  3. 扫描灰色对象匹配地址(一些白色对象可以变成灰色并添加到灰色列表的末尾)直到灰色集合完成
  4. 剩余的白色对象被认为是孤立的,并通过 /sys/kernel/debug/kmemleak 报告

一些分配的内存块具有存储在内核内部数据结构中的指针,它们不能被检测为孤儿。为了避免这种情况,kmemleak 还可以存储指向需要找到的块地址范围内地址的值的数量,以便该块不被视为泄漏。一个例子是 __vmalloc()。

使用方法

To display the details of all the possible scanned memory leaks::
cat /sys/kernel/debug/kmemleak
To trigger an intermediate memory scan::
echo scan > /sys/kernel/debug/kmemleak
To clear the list of all current possible memory leaks::
echo clear > /sys/kernel/debug/kmemleak

泄漏堆栈信息:

 当我们看到如上的堆栈信息后,即可知道我们的程序在那些地方会出现有可能的内存泄漏,然后我们感觉调用堆栈信息去查找相关代码,根据代码流程分析是否存在内存泄漏即可。

这个博客到目前就总结了以上内存泄漏的定位方法和一些概念性的东西,希望能帮到各位苦苦挣扎的C\C++程序员。也希望能抛砖引玉,有人分享更好的定位方法。

参考文献与链接:

Kernel Memory Leak Detector — The Linux Kernel documentation

用kmemleak检测内核内存泄漏 | Linux Performance

https://www.cnblogs.com/klcf0220/p/5502254.html

Kernel Memory Leak Detector — The Linux Kernel documentation

Kmemleak--Kernel space内存泄露分析工具 - SigmaStarDocs

相关文章:

内存泄漏 定位方法

目录 内存概念 物理内存 虚拟内存 内存泄漏 定位方法和手段 1.MemInFo MemTotal MemFree MemAvailable Cached 2 vmalloc info 3.Kmemleak 算法原理 使用方法 参考文献与链接: 如果你点进这篇文章,那么要么你是一个C\C程序员,…...

es-head插件插入查询以及条件查询(五)

es-head插件插入查询以及条件查询 1.es-head插件页面介绍 页面详细介绍 2.es-head查询语句 2.1.查询索引中的全部数据 curl命令交互,采用GET请求 语法格式: curl -XGET es地址:9200/索引名/_search?pretty [rootelaticsearch ~]# curl -XGET 192…...

安装python教程并解决Python安装完没有Scripts文件夹问题

安装python教程 并解决Python安装完没有Scripts文件夹问题 ** 一背景 **首先要了解这个出现的原因是下载安装的版本问题 系統是32 bit 的版本还是 64bit 的 web-based: 透过网络安装的,就是执行安装后才透过网络下载python executable: 可執行文件的&#xff…...

postman的断言、关联、参数化、使用newman生成测试报告

Potman 断言 Postman 断言简介 让 Postman工具 代替 人工 自动判断 预期结果 和 实际结果 是否一致断言代码 书写在 Tests 标签页中。 查看断言结果 Test Results 标签页 Postman 常用断言 1. 断言响应状态码 Status code:Code is 200 // 断言响应状态码为 200…...

春招大盘点:找工作除了招聘网站还有哪些渠道?

又是一年毕业季,估计同学们都正在写论文、找工作两头忙,很多同学和小C“诉苦”说现在找实习的渠道太少了,招聘网站都刷完了,也没看到很合适的岗位。那找工作除了招聘网站还有什么渠道呢?其实是有的,今天就为…...

eNSP 构建基本WLAN

配置项配置参数AP组 名称:hcia-group 应用模板:域管理模板hcia-domain、VAP模板hcia-vap 域管理模板 名称:hcia-domain 国家码:cn SSID模板 名称:hcia-ssid SSID名称:hcia-wlan 安全模板 名称:h…...

Python是不是被严重高估了?

Python起源一种shell的脚本语言 ,而现在已经发展成最通用的语言之一了,TIOBE指数的数据显示,Python是目前世界上最受欢迎的编程语言。 Python之所以这么受欢迎有很多原因。从Web开发到物联网编程再到AI等各个方面都能用到它。另外Python代码…...

给你一个购物车模块,你会如何设计测试用例?【测试用例设计】

测试购物车 从使用场景上,把自己想象成一个使用购物车的人,模拟流程,可以主要从两个方面进行考虑: 涉及操作:增(添加商品)删(删除商品)改(编辑、跳转商品&a…...

【wps】【毕业论文】三线表的绘制

目录 一、三线表 二、制作步骤 (1)点击“插入”——点击“表格”创建一个表格 (2)选中整个表格——鼠标右键选择“边框和底纹”,“表格属性”再点击“边框和底纹”——点击“自定义”——选择表格的边的宽度——如图…...

Spring Cloud Alibaba 多租户saas企业开发架构技术选型和设计方案

基于Spring Cloud Alibaba 分布式微服务高并发数据平台化(中台)思想多租户saas设计的企业开发架构,支持源码二次开发、支持其他业务系统集成、集中式应用权限管理、支持拓展其他任意子项目。 一、架构技术选型 核心框架 Spring Boot SOA Spring Cloud …...

Unity IL2CPP 游戏分析入门

一、目标 很多时候App加密本身并不难,难得是他用了一套新玩意,天生自带加密光环。例如PC时代的VB,直接ida的话,汇编代码能把你看懵。 但是要是搞明白了他的玩法,VB Decompiler一上,那妥妥的就是源码。 U…...

Python的23种设计模式(完整版带源码实例)

作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 Python的23种设计模式 一 什么是设计模式 设计模式是面对各种问题进行提炼和抽象而形成的解决方案。这些设计方案是前人不断试验&…...

OAuth2协议

OAuth2协议流程图协议角色和流程授权所需信息授权方式授权码模式(authorization code)参数简化模式密码模式客户端模式授权方式小结流程图 协议角色和流程 user-agent:浏览器或者手机App平台 资源所有者(resourc owner&#xff0…...

LeetCode-115. 不同的子序列

目录动态规划题目来源 115. 不同的子序列 动态规划 1.确定dp数组(dp table)以及下标的含义 dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。 2.确定递推公式 这一类问题,基本是要分析两种情况 t[i - 1…...

kubernetes scheduler 源码解析及自定义资源调度算法实践

kubernetes scheduler 浅析 什么是kubernetes scheduler? 小到运行着几十个工作负载的 kubernetes 集群,大到运行成千上万个工作负载 kubernetes 集群,每个工作负载到底应该在哪里运行,这需要一个聪明的大脑进行指挥&#xff0c…...

MySQL插入数据

目录 一、怎么样插入数据 二、通过命令提示窗口插入数据 三、使用PHP脚本插入数据 一、怎么样插入数据 在MySQL 表中可以使用 INSERT INTO SQL语句来插入数据。 可以通过 mysql> 命令提示窗口中向数据表中插入数据,或者通过PHP脚本来插入数据。 下面是向MyS…...

从GPT-4、文心一言再到Copilot,AIGC卷出新赛道?

业内人都知道,上一周是戏剧性的,每一天,都是颠覆各个行业,不断 AI 化的新闻。 OpenAI发布GPT-4、百度发布文心一言、微软发布Microsoft 365 Copilot 三重buff叠加,打工人的命运可以说是跌宕起伏,命途多舛了…...

1.2 从0开始学Unity游戏开发--运行原理

在我开始学习游戏开发的时候,有了好多年的客户端开发经验,并且刚毕业那会还使用cocos2dx做过一点小的2d横版过关游戏,因此对我来说做游戏开发到底是做什么还是比较清晰的,但是如果从来没做过游戏开发,甚至连客户端开发也没怎么做过的人可能没那么好理解游戏到底是怎么运作…...

【微信小程序】如何获得自己当前的定位呢?本文利用逆地址解析、uni-app带你实现

目录 前言 效果展示 一、在腾讯定位服务配置微信小程序JavaScript SDK 二、使用uni-app获取定位的经纬度 三、 逆地址解析,获取精确定位 四、小提示 前言 效果展示 一、在腾讯定位服务配置微信小程序JavaScript SDK 在浏览器搜索腾讯定位服务,找…...

92年程序员发帖晒薪资称自己很迷茫,网友:老弟你可以了

当下,是一个“向钱看,向厚赚”的社会。快节奏的生活下,家庭、工作各方面压力很容易使年轻人陷入迷茫和焦虑。 与其他行业相比,程序员的高薪让人羡慕。那么,对于那些真正达到这么多收入的人来说,他们是怎么…...

阿里四面,居然栽在一道排序算法上

前言 算法是程序的灵魂,一个优秀的程序是可以在海量的数据中,仍保持高效计算。目前各大厂的面试要求也越来越高,算法肯定会要去。如果你不想去大厂,只想去小公司,或许并不需要要求算法。但是你永远只能当一个代码工人&…...

macOS 13.3(22E252)/12.6.4/11.7.5正式版发布

系统介绍 3 月 28 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.3 更新(内部版本号:22E252)苹果今天还发布了macOS Monterey 12.6.4和macOS Big Sur 11.7.5,本次更新距离上次发布隔了 42 天。 macOS Ventura 带来…...

MPP数据库简介及架构分析

目录什么是MPP?特性并行处理超大规模数据仓库真正适合什么典型的分析工作量数据集中化线性可伸缩性MPP架构技术特性数据库架构分析Shared EverythingShared DiskShare MemoryShared NothingShared Nothing数据库架构优势什么是MPP? MPP (Massively Paral…...

centos7配置pytorch和tensorflow

1、安装anaconda 1.1镜像源下载对应anaconda版本后传到服务器上 1.2进入对应文件夹 首先赋权再执行安装程序 chmod x Anaconda3-2022.10-Linux-x86_64.sh ./Anaconda3-2022.10-Linux-x86_64.sh chmod x Anaconda3-2022.10-Linux-x86_64.sh 1.3交互确认 确认许可协议&…...

Kafka在Mac下的安装与使用

mac 安装kafka安装kafka的原因安装kafka启动Zookeeper启动Kafka创建topic查看topic生产数据消费数据关闭zookeeper关闭kafka测试安装kafka的原因 用户微服务登录后需要向广告微服务中发送用户登录的信息以获取用户画像(这个过程是异步的),故…...

AndroidStudio相对布局

目录 RelativeLayout常用属性(它们可以几个结合在一起使用): 相对于父容器居中 相对于父容器对齐 相对于其它控件位置 相对于其它控件对齐 标识符问题 实例演示 RelativeLayout类是ViewGroup的子类也就是相对布局 RelativeLayout常用属…...

如何用iOS自带摄像头进行拍摄获取视频流以及OpenCV图像处理实时显示

目录概述一、如何用Swift调用OpenCV库1.项目引入OpenCV库2.桥接OpenCV及Swift二、运用AVFoundation获取实时图像数据1.建立视频流数据捕获框架2.建立 Capture Session3.取得并配置 Capture Devices4.设定 Device Inputs5.配置Video Data Output输出6.工程隐私权限配置7.处理相机…...

智安网络|为什么说防火墙是我们信息安全的第一道防线?

网络安全现状: ①攻击者需要的技术水平逐渐降低,手段更加灵活,联合攻击急你的剧增多:网络蠕虫具有隐蔽性、传染性、破坏性、自主攻击能力,新一代网络蠕虫和黑客攻击、计算机病毒之间的界限越来越模糊 ②网络攻击趋利…...

Android多媒体功能开发(8)——使用VideoView控件播放视频

Android播放视频类主要有两种方式: VideoView控件SurfaceView控件MediaPlayer VideoView是SurfaceView的子类,实际上VideoView相当于SurfaceView MediaPlayer。SurfaceView支持的功能VideoView都支持。也可用VideoViewMediaPlayer的方式播放。 视频播放…...

python调用CC++

python调用C程序 一般来说在python调用C/C程序主要可以分为3步: 1、编写C/C实现程序。2、将C/C程序编译成动态库。-3、在Python中调用编译生成的库。Python在调用C/C程序时有一些不同,需要注意。 Python调用C语言程序比较简单,将C语言程序…...

购物网站 后台模板/网站死链检测工具

目录 一、Linux系统 1.识别当前系统的摄像头 2.想看看摄像头支持什么样的分辨率、帧率 3.ffmepg采集摄像头,封装成rtp推送到远端pc 二、windows系统 1.识别当前系统的摄像头 2.想看看摄像头支持什么样的分辨率、帧率 3.ffmepg采集摄像头,封装成rtp…...

桂阳网站制作公司/建设网站前的市场分析

1.1 设置ip地址 执行命令 service network restart 验证: ifconfig1.2 关闭防火墙 执行命令 service iptables stop 验证: service iptables status1.3 关闭防火墙的自动运行 执行命令 chkconfig iptables off 验证: chkconfig --list | grep iptables1.4 设置主机名 执行命令 …...

可以做网站吗/seo内部优化方式包括

前提概要: 动态路由协议可以按照工作范围区分为IGP(内部网关路由协议)以及EGP(外部网关路由协议)。IGP工作在同一个AS内部,主要用来发现以及计算路由,为AS内提供路由信息的交换;而E…...

做厂房出租有那些推广网站/松原头条新闻今日新闻最新

使用diff命令查看不同版本文件的差异。查看文件的差异&#xff1a;[rootzabbix-server ~]# diff test1.sh test2.sh 2c2,4< echo "hell world"---> echo "hello the world"> echo "test file"> 查看文件的差异&#xff0c;包含信息头…...

如何建设网站推广平台/百度账号人工申诉

数据内容&#xff1a;2014-2015年四川省、重庆市&#xff08;川渝地区&#xff09;零售商销售数据 数据格式&#xff1a;.csv格式 数据量&#xff1a;152万条 数据字段&#xff1a; a) YEARMONTH&#xff1a;销售年月 b) STORE_NAME&#xff1a;商店名称 c) LOCAL_CHANNEL_TYPE…...

电子工程网/北京谷歌seo

Vue开发搭建&#xff08;npm安装vue脚手架安装&#xff09;一、使用之前&#xff0c;我们先来掌握3个东西是用来干什么的。二、测试NPM安装vue-router一、使用之前&#xff0c;我们先来掌握3个东西是用来干什么的。 npm: Nodejs下的包管理器。 webpack: 它主要的用途是通过Com…...