首页 > 系统相关 >内存泄漏的概念及其产生原因和规避手段

内存泄漏的概念及其产生原因和规避手段

时间:2024-08-13 16:53:46浏览次数:13  
标签:泄漏 DoSth 对象 规避 引用 指针 内存

Memory leak

内存泄漏是指:程序在动态分配内存后,由于某种原因未能释放或无法释放这些内存,导致系统内存的浪费。

产生内存泄露的原因

上述定义表示了一种现象,没有定义原因。要避免这种现象,就要探究产生现象的原因。

内存泄漏是在程序运行过程中产生的,程序运行依赖的是我们的指令,即程序的源代码。

不同的编程语言其对内存使用方式的表现不同。有的是通过指针,依赖指针来申请与释放内存;有的语言有内存管理器,通过对象的引用数是否为 0 来决定是否自动回收该对象内存。

产生内存泄漏的原因,从内存指针的角度来说,是申请内存之后的代码逻辑失去了该内存的指针而不能释放内存,或者指针都在但忘记释放内存。

char *p1 = (char *) malloc(10); // 指针 p1 指向 内存地址 1
char *p2 = (char *) malloc(10); // 指针 p2 指向 内存地址 2
p1 = p2; // p1 与 p2 军指向内存地址 2,导致当前逻辑失去了之前申请的内存地址 1 的指针
// 由于我们编写的程序往往运行在主循环中,当前逻辑执行完,程序并不会结束运行。
// 所以在当前逻辑结束前如果没有释放内存,就会产生内存泄漏的问题。

从对象引用的角度来说,是当前逻辑失去了先前定义对象的引用。

具体表现是定义了一个对象,然后将它的引用交给变量或成员属性。在之后又将它的引用传递给其他的对象,但其他对象只是接收它并在内部使用,不向外部提供任何访问它或者取消对它的引用的方式。当该我们的代码逻辑不再需要这个对象时,将变量或成员属性置空,但此时其他对象仍持有它的引用,导致该对象所使用的内存无法回收。

Data data = new Data(); // 创建对象,赋值给变量,引用数为 1

DoSth doSth = new DoSth(); // 其他对象
doSth.addData(data); // 传递引用,引用数为 2

data = null; // 取消引用,引用数为 1
// 当前逻辑不能访问 Data 对象,也不再使用它,但是内存无法释放

如果 DoSth 对象的功能的实现依赖 Data 对象,而将 data 变量置空后,之后的逻辑依然依赖使用 DoSth 通过的功能,即使不能使 DoSth 对象取消其对 Data 对象的引用,也是合理的。

但是,如果将 data 变量置空的意图是完全不再使用该对象,那 DoSth 对象也不应该使用它,此时不能使 DoSth 对象取消其对 Data 对象的引用就是不合理的。逻辑上完全不被使用的数据依然占据的内存,导致内存管理器无法回收,这就产生了内存泄漏。

造成这个问题的原因是,两个对象的生命周期不一致,被引用对象的生命周期比引用它的对象的生命周期短。

上述情况在 GUI 程序设计中,使用观察者模式来设计响应式数据,并通过它使视图和数据交互时,如果使用不当,就会产生:

视图对象作为观察者向数据中传递其引用,数据对象在变化时通知视图更新,看起来很棒。但是当原来的视图被新的视图替换,不再被使用时,若数据不移除对视图的引用,会产生内存泄漏。

所以在应用观察者模式设计类似响应式数据这种观察者对象的时候,同时提供注册观察者与注销观察者的功能。

另外,引入生命周期的概念来保持逻辑上的同步能很好地解决内存泄漏的问题。

避免内存泄漏的办法

时刻牢记:

  • 当还需要使用内存或对象时,始终保持其指针或引用。
  • 当内存不再使用时,立即释放。
  • 当对象不再使用时,取消所有依赖它的对象对它的引用。这也就意味着若一个对象要引用其他对象,就同时要有取消引用的功能接口。

标签:泄漏,DoSth,对象,规避,引用,指针,内存
From: https://www.cnblogs.com/chaihuibin/p/18357274

相关文章

  • Java栈溢出|内存泄漏|内存溢出
    Java虚拟机栈是线程私有的,它的生命周期和线程同步一个线程每执行到一个方法,JVM就会创建一个栈帧(用于存储基本数据类型、对象指针和返回值等),并将栈帧压入栈中。代码示例:publicclassExample{publicstaticvoidmain(String[]args){Exampleexample=newExa......
  • freertos怎么查看任务内存是否溢出
    1.允许堆栈检测API的使用打开FreeRTOSConfig.h文件,找到宏INCLUDE_uxTaskGetStackHighWaterMark并将其值定为1。2.uxTaskGetStackHighWaterMark函数的说明点击查看代码/**函数参数:xTask:需要检查的堆栈情况的任务句柄。将xTask设置为NULL的话检测的就是调用这个函......
  • C++:内存管理
    C++内存管理的概念        C语言内存管理方式(malloc/free)在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。new/delete                    new/d......
  • C语言和C++中的动态内存管理------malloc和free的区别
    引言:动态内存管理:需要根据具体情况来设定需要的内存大小,同时可能需要大于1Mbyte的连续空间。此时我们无法使用静态数组。原因是因为静态数据的开辟是在栈空间,其次栈空间的大小在连续分配时不能超过1Mbyte,因此引入了动态内存管理。C语言C语言中动态内存管理的有四个函数:mal......
  • 快速认识JVM,深入掌握类加载器、JVM内存空间、JVM垃圾回收机制和双亲委派机制。
    什么是JVM    JVM(JavaVirtualMchine)java虚拟机,主要作用就是将Java字节码文件解释为能被各种操作系统理解的机器码。JVM的三大功能    1.解释和运行:将字节码文件翻译为能被各种操作系统理解的机器码。    2.内存分配:给对象及其方法分配内存,管理......
  • 如何在栈上动态分配内存?
    alloca是一个非标准的函数,用于在栈上分配内存。与malloc不同,alloca分配的内存会在当前函数返回时自动释放,不需要也不能显式地调用free来释放它。这使得alloca在需要快速分配和释放小块内存时非常方便,但也带来了一些使用上的风险。1.基本用法#include<iostream>#in......
  • 如何解决因内存不足导致的 iPhone 白苹果问题:原因解析与修复教程
    引言在使用iPhone的过程中,许多用户可能遇到过“白苹果”现象,即设备启动时只显示白色的Apple标志,却无法进入系统。这种情况通常让人感到困惑和担忧,尤其是当重要数据似乎无法访问时。本文将探讨内存不足导致iPhone白苹果的原因,并提供详细的修复教程,帮助你恢复设备正常运行......
  • Linux操作系统云主机中buffer和cache占用内存怎么办?
    问题描述系统长期运行后,free命令查看系统内存,发现剩余内存不足,大部分是buffer和cache。问题分析在Linux的内存管理中,buffer是Linux内存中的Buffercache。cache是Linux内存中的Pagecache。Buffercache:主要是当系统对块设备进行读写的时候,对块进行数据缓存的系统来使用,即......
  • JVM内存结构的划分
    5.3JVM内存结构的划分5.3.1栈(保存局部变量和方法调用的信息)栈也是线程私有的,在我们调用方法的时候,每调用一个方法,该方法就会进入栈中,当该方法执行完毕的时候就会从栈中移除。比如说现在要在main方法中调用A方法,在A方法中再调用B方法:但是,如果我们不停的调用方法,就会导致栈满......
  • 【待看】PHP内存性木马即PHP不死鸟
    https://mp.weixin.qq.com/s/KUA531d_3PKDsUSVgvX0CQPHP内存性木马即PHP不死鸟原创蓝胖子之家蓝胖子之家2023年09月17日00:00山东图片PHP内存性木马是一种比较隐蔽的恶意代码,它的特点是能够在服务器上保持持续运行,而且通常会创建隐蔽的后门,以便攻击者随时可以访问受感染......