发生内存泄漏后

news2024/12/4 17:31:35

        内存泄漏是指程序在运行过程中分配的内存无法被释放,导致内存使用量不断增加,最终可能导致程序崩溃或系统崩溃。

产生内存泄漏的原因

内存泄漏可能是由多种原因造成的,例如:

  • 忘记释放内存。由于项目比较大,一般申请内存的地方与释放内存的地方并不在一起,导致容易遗漏。例如,在C语言中,如果使用malloc()函数分配了内存,就必须使用free()函数来释放它。否则,这块内存就会一直占用着,直到程序结束。
  • 智能指针循环引用。多个对象相互引用,导致它们都无法被释放。同样在项目比较大的时候,由于维护的智能指针比较多,关系复杂时容易出现。例如,如果一个对象A引用了对象B,而对象B又引用了对象A,那么这两个对象都无法被释放。
  • 全局变量:全局变量在程序的整个生命周期内都存在,即使它们不再被使用。在一定程度上来讲,也是一种泄漏。

        如果是正常的使用全局变量,那内存的占用自然是合理的。但对于一些其它原因导致的内存泄漏,那就让人很头大了。影响小一点的,也就是自身应用的功能异常,影响大了,可能导致整个系统崩溃。

怎么搞

         我写了一个模拟内存泄漏的小程序,来演示一下具体的排查过程,运行程序前,执行free是这样的:

root@gl:/home/gl# free
              total        used        free      shared  buff/cache   available
Mem:        2025004      109884     1792128          92      122992     1778336
Swap:       2097148       87868     2009280

        执行后:

root@gl:/home/gl# free
              total        used        free      shared  buff/cache   available
Mem:        2025004     1181228      711804          92      131972      702484
Swap:       2097148       84796     2012352

        由于模拟的小程序逻辑比较简单,就先不放出名字了。实际线上环境排查问题的时候,面临比较多的也是这样的一个场景:有比较多的应用跑在一台服务器上,开始时是一头雾水的。

        由free的输出可以看出,系统总内存为2025004KB,即2GB,原有空闲内存1792128KB,约1.7GB,运行异常应用后,剩余内存一下子缩水到了711804KB,仅700MB。并且是used列增长了近1GB的大小,反而buf/cache变化不大。持续观察一会,会发现可用内存还在持续减少。这个时候的你:

        这个时候,自然而然就能想到,需要找出是哪个进程占用内存比较多呢?

top:

        命令行窗口输入top,输出默认是按cpu占用排序的,按 M 切换为按内存占用排序:

top - 03:00:12 up 57 min,  3 users,  load average: 0.01, 0.01, 0.00
Tasks: 122 total,   2 running,  71 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.2 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2025004 total,   710588 free,  1182252 used,   132164 buff/cache
KiB Swap:  2097148 total,  2012608 free,    84540 used.   701384 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                    
   1615 root      20   0 1055448 1.005g   1312 S   0.0 52.0   0:00.68 a.out                      
    894 root      20   0 1411024  18612   5476 S   0.0  0.9   0:01.03 dockerd                    
    713 root      20   0 1284616  12804   5932 S   0.0  0.6   0:06.93 containerd                 
    403 root      19  -1   74340  10932  10596 S   0.0  0.5   0:00.24 systemd-journal            
   ...         

        可疑进程"a.out"映入眼帘,虚拟内存VIRT与RES常驻内存占用高大1GB,跟free看到的内存增量也是能对应的上的。接下来要做的,就是看一下a.out这个程序是不是真的内存泄漏了。

内存泄漏检测工具

        memleak是一个开源的内存泄漏检测工具,可以帮助我们检测C/C++程序中的内存泄漏。它可以跟踪程序的内存分配和释放情况,并报告任何可疑的内存泄漏。类似地,还有valgrind也可以用,但memleak的好处是不用重启进程,可以直接观察运行中的进程行为,所以这里用memleak。

        执行memleak命令,并通过-p指定可疑进程pid:

root@gl:/home/gl# memleak-bpfcc -p 1615
Attaching to pid 1615, Ctrl+C to quit.
[03:06:12] Top 10 stacks with outstanding allocations:
        10485760 bytes in 10 allocations from stack
                fun+0x1f [a.out]
                main+0x12 [a.out]
                __libc_start_call_main+0x80 [libc.so.6]
[03:06:17] Top 10 stacks with outstanding allocations:
        15728640 bytes in 15 allocations from stack
                fun+0x1f [a.out]
                main+0x12 [a.out]
                __libc_start_call_main+0x80 [libc.so.6]
^Croot@gl:/home/gl# 

        观察一会后CTRL+C停止掉,从输出中可以看出,memleak在截至 [03:06:12] 的时间点,检测到了10次内存分配,总计分配了10485760字节(即10MB),这些分配尚未被释放。紧接着,可以看到申请内存的堆栈:即main函数中的fun调用。

        接下来就比较简单了,找到a.out的源码分析一下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void fun() {
        int i = 0;
        while (i++ < 2048) {
                int* p = (int*)malloc(1024 * 1024);
                memset(p, 0, 1024 * 1024);
                *p = i;
                printf("%d MB\n", *p);

                if (i > 1024) {
                        sleep(1);
                }
        }
}

int main() {
        fun();
        pause();

        return 0;
}

        看到这里你估计就要笑了,这是哪个沙雕写出的代码?很明显可以看出,是由于fun函数中的malloc没有调用对应的free,我们补上free调用就可以了。然而实际项目中,代码看起来并不是这么直接的,申请后的内存是要拿来使用的,你得找到一个合适的地方才能释放它。这就可以喝杯茶慢慢再分析了~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1412339.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑自动开机播放PPT的解决方案

客户有个需求&#xff0c;要求与LED大屏幕连接的电脑定时自动播放PPT。为了安全电脑在不播放的时段&#xff0c;必须关机。 目录 1、使用“时控插座”并进行设置 2、戴尔电脑BIOS设置&#xff08;上电开机&#xff09; 3、设置Windows自动登录 4、任务计划设置 5、启动Au…

数据结构与算法-二叉树-路径总和lll

路径总和lll 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节…

华为配置ACL限制用户通过Telnet登录设备

配置ACL限制用户通过Telnet登录设备示例 组网需求 如图1所示&#xff0c;PC与设备之间路由可达&#xff0c;用户希望简单方便的配置和管理远程设备&#xff0c;可以在服务器端配置Telnet用户使用AAA验证登录&#xff0c;并配置安全策略&#xff0c;保证只有符合安全策略的用户才…

Zoomit 安装与使用

Zoomit 安装与使用 1&#xff09;工具介绍 ZoomIt 是一款非常实用的投影演示辅助软件 ZoomIt 是一种在所有 Windows 设备上运行的工作的注释和缩放工具 2&#xff09;下载地址 地址&#xff1a;https://zoomit.en.softonic.com/ 3&#xff09;安装教程 第一步 第二步 …

演讲《罗振宇2024“时间的朋友”跨年演讲》观后感

虽然看罗老师的跨年演讲&#xff0c;已经过去快一个月了&#xff0c;但是自己认为还是非常值得写观后感的&#xff0c;本身罗老师的演讲&#xff0c;也是自己非常喜欢的&#xff0c;所以每年元旦&#xff0c;跟随罗老师过跨年&#xff0c;已经是自己的习惯了。 就像赵本山大叔…

低代码:为消防数字化管理系统建设插上高效的翅膀

随着科技的不断进步&#xff0c;数字化转型已经成为各行各业发展的必然趋势。消防行业作为保障公共安全的重要领域&#xff0c;也面临着数字化转型的迫切需求。 “2023年10月27日&#xff0c;国家综合性消防救援队伍信息化工作暨现场联合作战指挥通信体系示范建设现场会在内蒙古…

Linux基础指令大汇总

Linux的指令比较多&#xff0c;在学习的过程中要学会总结和归纳&#xff0c;同时结合实践多多使用&#xff0c;就像学数学一样&#xff0c;不是背过公式就等于掌握的&#xff0c;而是要知道在什么时候用&#xff0c;怎么用才是关键。 这篇文章会列举一系列常用的指令&#xff0…

HTTP3/QUIC 性能测试与配套组件

背景 最近一年很多关于QUIC的文章层出&#xff0c;但是发现一个问题&#xff0c;这些文章都是在介绍QUIC或HTTP3是怎样的一个东西&#xff0c;以及它的优点和机制&#xff0c;将它夸的近乎上天了。然而有心的人估计会亲手做一些测试&#xff0c;就会发现这个被捧上天的东西性能…

物联网IOT视频设备如何快速对接阿里云生活物联网(Link Visual)并成功上云?

原文永久更新地址&#xff1a;https://www.yundashi168.com/472.html 文章来源&#xff1a;猿视野 如果有图片看不清楚&#xff0c;加载不出来&#xff0c;请阅读原文。 什么是Link Visual、 Link Visual是生活物联网平台针对视频产品推出的增值服务&#xff0c;提供视频数据上…

php下curl发送cookie

目录 一&#xff1a;使用 CURLOPT_COOKIE 选项 二&#xff1a;CURLOPT_COOKIEFILE 三&#xff1a;CURLOPT_HTTPHEADER php curl发送cookie的几种方式,下面来介绍下 一&#xff1a;使用 CURLOPT_COOKIE 选项 通过设置 CURLOPT_COOKIE 选项&#xff0c;你可以将 cookie 字符…

将 Amazon Bedrock 与 Elasticsearch 和 Langchain 结合使用

Amazon Bedrock 是一项完全托管的服务&#xff0c;通过单一 API 提供来自 AI21 Labs、Anthropic、Cohere、Meta、Stability AI 和 Amazon 等领先 AI 公司的高性能基础模型 (FMs) 选择&#xff0c;以及广泛的 构建生成式 AI 应用程序所需的功能&#xff0c;简化开发&#xff0c;…

基于Grafana+Prometheus搭建可视化监控系统实践

基本介绍 Grafana&#xff1a;一个监控仪表系统&#xff0c;可以根据提供的监控数据&#xff0c;生产可视化仪表盘&#xff0c;同时也具有告警通知功能。这里的监控数据来源&#xff0c;目前主要以Prometheus为主&#xff08;也支持其它数据源&#xff09;&#xff0c;每次展现…

day10_面向对象

今日内容 零、 复习昨日 一、this关键字 二、构造方法 三、重载 零、 复习昨日 1 类和对象是什么关系? 类是模板,对象是实例对象是由类创建的 2 类中有什么?(类的成员) 成员属性(成员变量)成员方法 3 创建对象的语法? 类名 对象名 new 类名(); 4 调用对象属性的语法 对象.属…

CLion编辑器中文乱码

1.首先设置编码格式 都设置成utf-8 调整注册表 搜索regis

泽众云真机-机型集中化运维方案升级全面完成

2024年元月份&#xff0c;泽众云真机运维团队&#xff0c;经过几个月软硬件多轮安装调试&#xff0c;机型集中化运维方案升级全面完成。解决了云真机的机型集中化运维难题&#xff0c;方便了运营人员手机管理。 具体如下&#xff1a; 1、集中化运维&#xff0c;如服务器、PC、…

智能分析网关V4智慧冶金工厂视频智能监管方案

一、背景与需求 随着工业4.0的推进&#xff0c;冶金行业正面临着转型升级的压力。为了提高生产效率、降低能耗、保障安全&#xff0c;冶金智能工厂视频监管方案应运而生。该方案通过高清摄像头、智能分析技术、大数据处理等手段&#xff0c;对工厂进行全方位、实时监控&#xf…

svn和git的本质区别是什么

参考&#xff1a; https://blog.csdn.net/feiying0canglang/article/details/126550676 上边图中&#xff0c;跨越了区的箭头&#xff0c;它中间的区数据都会同步。例如&#xff1a;git checkout &#xff0c;它是将本地仓库数据更新到暂存区和工作区的。\ 理解 gitlab和svn都…

五金压铸ERP软件有什么用?能帮助企业处理哪些难点

不同类型的五金压铸产品有不同的规格、质量、销售渠道、价格策略等&#xff0c;日常经营管理过程中存在的难点复杂多样。 近些年社会可的发展进步也不断推动五金压铸行业管理模式的变更&#xff0c;现如今逐渐朝着智能化和信息化方向发展。而在这个时代背景之下&#xff0c;有…

Jellyfin影音服务本地部署并结合内网穿透实现公网访问本地资源

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

系统架构设计师教程(十六)嵌入式系统架构设计理论与实践

嵌入式系统架构设计理论与实践 16.1 嵌入式系统概述16.1.1 嵌入式系统发展历程16.1.2 嵌人式系统硬件体系结构16.2 嵌入式系统软件架构原理与特征16.2.1 两种典型的嵌入式系统架构模式16.2.2 嵌入式操作系统16.2.3 嵌入式数据库16.2.4 嵌入式中间件16.2.5 嵌入式系统软件开发环…