什么是内存泄漏?

news/2024/11/5 18:54:33/

1 内存泄漏的定义

内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

内存泄漏通常情况下只能由获得程序源代码的程序员才能分析出来。

2 内存泄漏导致的后果

内存泄漏会因为减少可用内存的数量从而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉导致全部或部分设备停止正常工作,或者应用程序崩溃。

内存泄漏带来的后果可能是不严重的,有时甚至能够被常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。

在以下情况,内存泄漏导致较严重的后果:

  • 程序运行后置之不理,并且随着时间的流逝消耗越来越多的内存(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务可能被运行后很多年内都置之不理);
  • 新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时;
  • 程序能够请求即使在程序终止之后也不会被释放的内存(比如共享内存);
  • 泄漏在操作系统内部发生;
  • 泄漏在系统关键驱动中发生;
  • 内存非常有限,比如在嵌入式系统或便携设备中;
  • 当运行于一个程序终止时内存并不自动释放内存的操作系统(比如AmigaOS)之上时。

3 内存泄漏的案例

3.1 C语言

下面是一个C语言的例子,在函数f()中申请了内存却没有释放,导致内存泄漏。当程序不停地重复调用这个有问题的函数f,申请内存函数malloc()最后会在程序没有更多可用存储器可以申请时产生错误(函数输出为NULL)。但是,由于函数malloc()输出的结果没有加以出错处理,因此程序会不停地尝试申请存储器,并且在系统有新的空闲内存时,被该程序占用。注意,malloc()返回NULL的原因不一定是因为前述的没有更多可用存储器可以申请,也可能是逻辑地址空间耗尽,在Linux环境上测试的时候后者更容易发生。

 #include <stdio.h>#include <stdlib.h>void f(void){void* s;s = malloc(50); /* 申请内存空间 */return;  /* 内在泄漏 - 参见以下资料 */ /* * s 指向新分配的堆空间。* 当此函数返回,离开局部变量s的作用域后将无法得知s的值,* 分配的内存空间不能被释放。** 如要「修复」这个问题,必须想办法释放分配的堆空间,* 也可以用alloca(3)代替malloc(3)。* (注意:alloca(3)既不是ANSI函数也不是POSIX函数)*/}int main(void){/* 该函数是一个死循环函数 */while (true) f(); /* Malloc函数迟早会由于内存泄漏而返回NULL*/return 0;}

3.2 C++

以下例子中,存储了整数123的内存空间不能被删除,因为地址丢失了。这些空间已无法再使用。

#include <iostream>
using namespace std;
int main()
{ int *a = new int(123);cout << *a << endl;// We should write "delete a;" herea = new int(456);cout << *a << endl;delete a;return 0;
}

3.3 Java

Java中的内存泄露,广义并通俗的说,就是:不再会被使用的对象的内存不能被回收,就是内存泄露。

Java中的内存泄露与C++中的表现有所不同。

C++中,所有被分配了内存的对象,不再使用后,都必须程序员手动的释放他们。所以,每个类,都会含有一个析构函数,作用就是完成清理工作,如果我们忘记了某些对象的释放,就会造成内存泄露。

但是在Java中,我们不用(也没办法)自己释放内存,无用的对象由GC自动清理,这也极大的简化了我们的编程工作。但,实际有时候一些不再会被使用的对象,在GC看来不能被释放,就会造成内存泄露。

对象都是有生命周期的,有的长,有的短,****如果长生命周期的对象持有短生命周期的引用,就很可能会出现内存泄露****。

public class Simple {Object object;//这是类中的属性,也是该类中的一个全局变量public void method1(){object = new Object();//...其他代码}
}

分析:在method1方法中,给类的属性赋了值,也就是在堆中创建一个对象,并将object指向该对象。但是当method1方法执行完之后,该object对象就不再被使用了。且object对象并没有直接被垃圾回收掉,只有等到Simple类创建的对象被释放之后,object才会被垃圾回收掉,所以这就有可能导致内存泄漏,也就是说:object这块内存地址不受程序控制了。

安全的写法:

public class Simple {Object object;public void method1(){object = new Object();//...其他代码object = null;}
}

从代码中可以看到,当在局部方法中使用完全局变量之后,随即将其释放掉,这样javaGC就会将object对象给回收掉。

4 内存泄漏的影响

如果一个程序存在内存泄漏并且它的内存使用量稳定增长,通常不会有很快的症状。每个物理系统都有一个较大的内存量,如果内存泄漏没有被中止(比如重启造成泄漏的程序)的话,它迟早会造成问题。

大多数的现代计算机操作系统都有存储在RAM芯片中主内存和存储在次级存储设备如硬盘中的虚拟内存,内存分配是动态的——每个进程根据要求获得相应的内存。访问活跃的页面文件被转移到主内存以提高访问速度;反之,访问不活跃的页面文件被转移到次级存储设备。当一个简单的进程消耗大量的内存时,它通常占用越来越多的主内存,使其他程序转到次级存储设备,使系统的运行效率大大降低。甚至在有内存泄漏的程序终止后,其他程序需要相当长的时间才能切换到主内存,恢复原来的运行效率。

当系统所有的内存全部耗完后(包括主内存和虚拟内存,在嵌入式系统中,仅有主内存),所有申请内存的操作将失败。这通常导致程序试图申请内存来终止自己,或造成分段内存访问错误(segmentation fault)。现在有一些专门为修复这种情况而设计的程序,常用的办法是预留一些内存。值得注意的是,第一个遭遇得不到内存问题的程序有时候并不是有内存泄漏的程序。

一些多任务操作系统有特殊的机制来处理内存耗尽得情况,如随机终止一个进程(可能会终止一些正常的进程),或终止耗用内存最大的进程(很有可能是引起内存泄漏的进程)。另一些操作系统则有内存分配限制,这样可以防止任何一个进程耗用完整个系统的内存。这种设计的缺点是有时候某些进程确实需要较大数量的内存时,如一些处理图像,视频和科学计算的进程,操作系统需要重新配置。

如内存泄漏发生在内核,表示操作系统自身发生了问题。那些没有完善的内存管理的计算机,如嵌入式系统,会因为一个长时间的内存泄漏而崩溃。

一些被公众访问的系统,如网络服务器或路由器很容易被黑客攻击,加入一段攻击代码,而产生内存泄漏。

写在最后

欢迎大家关注鄙人的公众号【麦田里的守望者zhg】,让我们一起成长,谢谢。
微信公众号


http://www.ppmy.cn/news/706916.html

相关文章

什么是随机存取_内存和存储器有什么区别?

内存和存储器在计算机中扮演不同的角色。内存可以满足临时数据访问需求,而存储器可以长期保留数据和其他文件。 内存和存储器这两个术语均指计算机的内部存储空间。内存是应用程序在处理过程中放置其使用的数据的地方。而存储器是存放数据以便长期或短期保留的地方。 传统上,…

什么是大端存储和小端存储

大端存储模式&#xff1a;数据的低位保存在内存的高地址中&#xff0c;数据的高位保存在内存的低地址中。 小端存储模式&#xff1a;数据的低位保存在内存的低地址中&#xff0c;数据的高位保存在内存的高地址中。

计算机存储溢出 是什么意思,数据溢出是什么意思

原标题&#xff1a;数据溢出是什么意思 数据溢出 在计算机中&#xff0c;当要表示的数据超出计算机所使用的数据的表示范围时&#xff0c;则产生数据的溢出。 溢出原因 数据类型超过了计算机字长的界限就会出现数据溢出的情况。导致内存溢出问题的原因有很多&#xff0c;比如&a…

计算机系统中引入虚拟内存的好处是什么,虚拟内存的作用是什么

虚拟内存是电脑中的一种内存管理的技术&#xff0c;有它才能下载日常生活中需要的软件&#xff0c;那么虚拟内存的作用到底是什么呢&#xff0c;今天就和大家一起来看看虚拟内存的作用到底是什么。 虚拟内存的作用介绍&#xff1a; 1、每个运行在Windows环境下的进程&#xff0…

工作内存与主内存是什么,硬件层面的存储架构是什么样,线程的实现原理是什么

工作内存与主内存 java内存模型并不真正的存在&#xff0c;是一种规则规定了程序中各个变量的访问方式。线程运行的时候&#xff0c;每个线程创建时候jvm都会为其创建一个工作内存&#xff0c;java的所有的变量都存放在主内存中是共享的数据区域。线程对变量进行操作&#xff…

java的栈区 堆区存放什么_简单整理java中的栈内存, 堆内存是什么?

上一篇文章简单整理了栈(stack), 堆(heap), 队列(queue)的结构 这一篇继续整理java中的 占内存,堆内存。 Java把内存划分成两种:一种是栈内存,一种是堆内存。 这里需要解释一下, 这里的堆内存是跟数据结构的堆是完全两码事。 一、栈内存 存放基本类型的变量,以及对象的引用…

计算机存储容量的基本单位pb,pb存储单位是什么

pb存储单位是一种计算机存储单位&#xff0c;pb的英文全称是Petabytes&#xff0c;其中文名叫拍字节&#xff1b;计算机存储单位一般用字节Byte、千字节KB、兆字节MB、吉字节GB、太字节TB、拍字节PB、艾字节EB等表示。 本文操作环境&#xff1a;Windows7系统&#xff0c;Dell G…

计算机中存储器的最小单位是什么意思,计算机内存储器的最小存储单位是什么...

计算机存储信息的最小单位&#xff0c;称之为位(bit&#xff0c;又称比特) 存储器中所包含存储单元的数量称为存储容量&#xff0c;其计量基本单位是字节(Byte。简称B)&#xff0c;8个二进制位称为1个字节&#xff0c;此外还有KB、MB、GB、TB等&#xff0c;它们之间的换算关系是…