黑马程序员技术交流社区

标题: 关于内存泄露的问题 [打印本页]

作者: 赵永康    时间: 2012-9-21 10:27
标题: 关于内存泄露的问题
各位大侠,本人在看张老师的视频的时候,他提及到了好几次说内存泄露的问题,我就是搞不明白,内存泄露到底是什么意思???如果发生了,对我们的程序会有什么影响,会对我们的电脑有啥影响吗??不甚求解....听起来很可怕啊
作者: 李健_8    时间: 2012-9-21 10:37
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的,使用完后必须显式释放的内存。应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理,所以关于这个问题,你不必太纠结,不会影响我们java程序员编程的
作者: 霍永刚    时间: 2012-9-21 10:40
以发生的方式来分类,内存泄漏可以分为以下四类。
(1)常发性内存泄漏。
发生内存泄漏的代码会被多次执行到,每次被执行时候都会导致一块内存泄漏。
(2)偶发性内存泄漏。
发生内存泄漏的代码只有在某些特定环境或操作过程中才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
(3)一次性内存泄漏。
发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致有且仅有一块内存发生泄漏。
(4)隐式内存泄漏。
程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格地说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存,但是对于一个服务器程序,需要运行几天几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存,所以称这类内存泄漏为隐式内存泄漏。
作者: 程金    时间: 2012-9-21 10:54
编程中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期。从申请分配、到使用、再到最后的释放。这样的过程非常灵活,但是却十分繁琐,程序员很容易由于疏忽而忘记释放内存,导致可用内存减少,从而导致内存的泄露。Java语言对内存管理做了自己的优化,这就是垃圾回收机制。Java的几乎所有内存对象都是在堆内存上分配(基本数据类型除外),然后由GC负责自动回收不再使用的内存,所以java内存泄漏比较少,比如张老师提到过的,根据对象hashcode值检索对象的hashmap中,如果你改变了hashmap中某个对象中参与hashcode运算的属性值的话,他的hashcode就会前后不一致, 你在删除这对象的的时候,无法删除那个对象,一直占用内存,造成内存泄漏.
作者: 陈振兴    时间: 2012-9-21 12:46
本帖最后由 陈振兴 于 2012-9-21 12:50 编辑

1.垃圾回收只与内存有关。垃圾回收的唯一原因就是为了回收程序中不再使用的内存。
所以对于与垃圾回收有关的任何行为来说,尤其是finalize()方法,它们也必须同内存及回收有关。
2.垃圾回收器都会负责释放对象占据的所有内存,这就是将finalize()的需求限制到特殊情况下,你通过某种非“创建对象”的方式为对象分配了存储空间。最重要的一点就是不能过多的去调用finalize()。所以我们在写程序的时候不会去调用这个方法,而是有java的GC来做这件事情的。
3.主要造成的原因:内存对象明明已经在不需要的时候,还仍然保留着这块内存和它的访问方式(引用)
Vector v = new Vector(10); 栈中存在Vector对象的引用v和Object对象的引用obj
for(int i=0;i<100;i++){         在For循环中,我们不断的生成新的对象,
Object obj = new Object();
v.add(obj);        
obj=null;            将obj引用置空。问题是当obj引用被置空后,不能被GC调用,
}
也就是说尽管obj引用已经被置空,但是Object对象仍然存在其他的引用,是可以被访问到的,所以GC无法将其释放掉。在for循环,Object对象对程序已经没有任何作用,所以此程序就会发生内存泄露。
对我们的电脑影响就是死机,所以在程序写完后会做压力测试的还有系统运行的稳定性能。
作者: 张忠豹    时间: 2012-9-21 13:23
本帖最后由 张忠豹 于 2012-9-21 13:25 编辑

先求给分啊!!!

我的理解,其实一般出现上述现象,是没有理解对象引用和值引用的概念。
8种基础数据类型的引用是值引用,其它都是对象引用。在这里我们不能将对象引用理解为C语言中指针指向对象的存储地址,应该理解为引用的复制。

因而当调用某个方法时,里面引用了某个对象,当你在这个方法执行完之前,将这个引用至为空时,只是将你复制那个引用至为空,而对象本身的引用依然存在,因此,java中的垃圾机制并不会将该对象回收。

这就造成了该对象在该系统一直运行时,一直驻留在内存中,慢慢占据着内存。从而出现内存泄露的故障。




作者: 狄琛林    时间: 2012-9-21 18:01
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。以下这段小程序演示了堆内存发生泄漏的情形:   void MyFunction(int nSize)   {   char* p= new char[nSize];   if( !GetStringFrom( p, nSize ) ){   MessageBox(“Error”);   return;   }   …//using the string pointed by p;   delete[] p;   }   当函数GetStringFrom()返回零的时候,指针p指向的内存就不会被释放。这是一种常见的发生内存泄漏的情形。程序在入口处分配内存,在出口处释放内存,但是c函数可以在任何地方退出,所以一旦有某个出口处没有释放应该释放的内存,就会发生内存泄漏。

内存泄漏会因为减少可用内存的数量从而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉导致全部或部分设备停止正常工作,或者应用程序崩溃。   内存泄漏可能不严重,甚至能够被常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。   在以下情况,内存泄漏导致较严重的后果:   * 程序运行后置之不理,并且随着时间的流失消耗越来越多的内存(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务可能被运行后很多年内都置之不理)   * 新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时   * 程序能够请求未被释放的内存(比如共享内存),甚至是在程序终止的时候   * 泄漏在操作系统内部发生   * 泄漏在系统关键驱动中发生   * 内存非常有限,比如在嵌入式系统或便携设备中   * 当运行于一个终止时内存并不自动释放的操作系统(比如AmigaOS)之上,而且一旦丢失只能通过重启来恢复。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2