精华内容
下载资源
问答
  • 一、什么是内存泄漏(memory leak)? 参考阮一峰老师博客:http://www.ruanyifeng.com/blog/2017/04/memory-leak.html 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。 程序的运行需要内存。只要...

    一、什么是内存泄漏(memory leak)?

    参考阮一峰老师博客:http://www.ruanyifeng.com/blog/2017/04/memory-leak.html

    不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。

    程序的运行需要内存。只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存。

    对于持续运行的服务进程(daemon),必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。

    C 语言代码,malloc方法用来申请内存,使用完毕之后,必须自己用free方法释放内存。

    这很麻烦,所以大多数语言提供自动内存管理,减轻程序员的负担,这被称为"垃圾回收机制"(garbage collector)。

     二、JavaScript 的垃圾收集机制

    JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占的内存,因为只要执行流进入相应的环境,就可能用到它们。而当变量离开环境时,这将其 标记为“离开环境”。

    常见内存泄漏的原因 :

    1、全局变量引起的内存泄漏

    function leaks(){  
        leak = 'xxxxxx';    //leak 成为一个全局变量,不会被回收
    }

    尤其当全局变量用于 临时存储和处理大量信息时,需要多加小心。如果必须使用全局变量存储大量数据时,确保用完以后把它设置为 null 或者重新定义。

    与全局变量相关的增加内存消耗的一个主因是缓存。缓存数据是为了重用,缓存必须有一个大小上限才有用。高内存消耗导致缓存突破上限,因为缓 存内容无法被回收。

    2、闭包引起的内存泄漏

    闭包是 JavaScript 开发的一个关键方面:匿名函数可以访问父级作用域的变量。

    var leaks = (function(){  
        var leak = 'xxxxxx';// 被闭包所引用,不会被回收
        return function(){
            console.log(leak);
        }
    })()
    
    123456

     3、dom清空或删除时,事件未清除导致的内存泄漏

    <div id="container"></div>
    
    $('#container').bind('click', function(){
        console.log('click');
    }).remove();
    
    //导致内存泄漏
    <div id="container"></div>
    
    $('#container').bind('click', function(){
        console.log('click');
    }).off('click').remove();
    
    //把事件清除了,即可从内存中移除

    子元素存在引用引起的内存泄漏:

    假如你的 JavaScript 代码中保存了表格某一个 <td> 的引用。将来决定删除整个表格的时候,直觉认为 GC 会回收除了已保存的 <td> 以外的其它节点。

    实际情况并非如此:此<td> 是表格的子节点,子元素与父元素是引用关系。由于代码保留了 <td> 的引用,导致整个表格仍待在内存中。

    4、被遗忘的计时器或回调函数

    var someResource = getData(); 
    setInterval(function() { 
        var node = document.getElementById('Node'); 
        if(node) { 
            // 处理 node 和 someResource 
            node.innerHTML = JSON.stringify(someResource)); 
        } 
    }, 1000); 
    

    如果 id 为 Node 的元素从 DOM 中移除, 该定时器仍会存在, 同时, 因为回调函数中包含对 someResource 的引用, 定时器外面的 someResource 也不会被释放。

    怎样避免内存泄露:

    1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;

    2)注意程序逻辑,避免“死循环”之类的 ;

    3)避免创建过多的对象 原则:不用了的东西要及时归还。

    三、什么是内存溢出(out of menory)? 

    内存溢出(out of memory):程序要求的内存,超出了系统所能分配的范围

    如:我们用一个int型4字节的数据来装一个float型8字节的数据,就会产生内存溢出。不过我们在编程是可以强制类型转换int XX = (int)float;只取float 4字节数据给int。

    展开全文
  • 内存泄漏的危害 内存泄漏的危害就是会使虚拟机占用内存过高,导致OOM(内存溢出),使程序异常。 对于一个Android应用来说,打开一个Activity,使用完后关闭,出现内存泄漏;又打开,又关闭,又泄漏;次之后,程序...

    参考网站:https://blog.csdn.net/Gods_magic/article/details/85255860 

    内存泄漏的危害 

    内存泄漏的危害就是会使虚拟机占用内存过高,导致OOM(内存溢出),使程序异常。

    对于一个Android应用来说,打开一个Activity,使用完后关闭,出现内存泄漏;又打开,又关闭,又泄漏;几次之后,程序占用的内存就会超过系统的限制,导致FC。

     

    public class TestActivity extends AppCompatActivity {
        private Handler handler = new Handler();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
    
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
    
                }
            },10000);
            finish();
        }
    }
    
    
     public static class MyHandler extends Handler{
            private WeakReference<TestActivity> mActivity;
    
            public MyHandler(TestActivity activity){
                mActivity = new WeakReference(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                if (mActivity.get() == null) {
                    return;
                }
    
                //接受到消息的处理
            }
        }
    展开全文
  • 内存泄漏几种情况

    2020-03-10 13:35:02
    几种内存泄漏的情况: 1、类的构造函数和析构函数没有匹配调用new和delete 2、在释放内存前程序出现错误。 3、释放对象数组时delete没有加上[ ] .4、指向对象的指针数组不等同于对象数组。对象数组,只需delete...

    几种内存泄漏的情况

    1、类的构造函数和析构函数没有匹配调用new和delete

    2、在释放内存前程序出现错误。

    3、释放对象数组时delete没有加上[ ]

    .4、指向对象的指针数组不等同于对象数组。对象数组,只需delete[]p,指向对象的指针数组,delete[]p只是释放了每个指针,但并没有释放对象的空间,正确的做法,是通过一个循环,将每个对象释放了呢,然后再把指针释放了。

    5、缺少拷贝构造函数(两次释放同一个内存是一种错误的做法,同时可能会造成堆的崩溃,按值传递会调用拷贝构造函数,引用传递不会调用)

    6、缺少重载赋值运算符。

    7、没有将基类的析构函数定义为虚函数(当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数不会被调用,子类的资源没有正确的释放,因此造成内存泄漏。)

    8、浅拷贝:如果复制的对象中引用了一个外部内容(例如分配在堆上的数据),那么在复制这个对象的时候,让新旧两个对象指向同一个外部内容,就是浅拷贝。(指针虽然复制了,但所指向的空间内容并没有复制,而是由两个对象共用,两个对象不独立,删除空间存在)  深拷贝:如果在复制这个对象的时候为新对象制作了外部对象的独立复制,就是深拷贝。

    所以引入了智能指针。

    展开全文
  • C语言中的指针和内存泄漏几种情况

    万次阅读 多人点赞 2016-12-14 16:30:19
    C语言中的指针和内存泄漏几种情况

    引言

    原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址。

    对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏。这些的确是消耗了开发人员大多数调试时间的事项。指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具。

    本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密。本文内容包括:

    • 导致内存破坏的指针操作类型
    • 在使用动态内存分配时必须考虑的检查点
    • 导致内存泄漏的场景

    如果您预先知道什么地方可能出错,那么您就能够小心避免陷阱,并消除大多数与指针和内存相关的问题。

    什么地方可能出错?

    有几种问题场景可能会出现,从而可能在完成生成后导致问题。在处理指针时,您可以使用本文中的信息来避免许多问题。

    常见的内存错误及其对策如下:

    1、内存分配未成功,却使用了它

        编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数

    的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

    2、内存分配虽然成功,但是尚未初始化就引用它

      犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。

        内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零

    值也不可省略,不要嫌麻烦。

    3、内存分配成功并且已经初始化,但操作越过了内存的边界

    例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

    4、忘记了释放内存,造成内存泄露

    含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。

    未初始化的内存

    在本例中,p 已被分配了 10 个字节。这 10 个字节可能包含垃圾数据,如图 1 所示。

    char *p = malloc ( 10 );

    图 1. 垃圾数据

    如果在对这个 p 赋值前,某个代码段尝试访问它,则可能会获得垃圾值,您的程序可能具有不可预测的行为。p 可能具有您的程序从未曾预料到的值。

    良好的实践是始终结合使用 memset 和 malloc,或者使用 calloc

    char *p = malloc (10);
    memset(p,’\0’,10);

    现在,即使同一个代码段尝试在对 p 赋值前访问它,该代码段也能正确处理 Null 值(在理想情况下应具有的值),然后将具有正确的行为。

    内存覆盖

    由于 p 已被分配了 10 个字节,如果某个代码片段尝试向 p 写入一个 11 字节的值,则该操作将在不告诉您的情况下自动从其他某个位置“吃掉”一个字节。让我们假设指针 q 表示该内存。

    图 2. 原始 q 内容

    图 3. 覆盖后的 q 内容

    结果,指针 q 将具有从未预料到的内容。即使您的模块编码得足够好,也可能由于某个共存模块执行某些内存操作而具有不正确的行为。下面的示例代码片段也可以说明这种场景。

    char *name = (char *) malloc(11); 
    // Assign some value to name
    memcpy ( p,name,11); // Problem begins here

    在本例中,memcpy 操作尝试将 11 个字节写到 p,而后者仅被分配了 10 个字节。

    作为良好的实践,每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。一般情况下,memcpy 函数将是用于此目的的检查点。

    内存读取越界

    内存读取越界 (overread) 是指所读取的字节数多于它们应有的字节数。这个问题并不太严重,在此就不再详述了。下面的代码提供了一个示例。

    char *ptr = (char *)malloc(10);
    char name[20] ;
    memcpy ( name,ptr,20); // Problem begins here

    在本例中,memcpy 操作尝试从 ptr 读取 20 个字节,但是后者仅被分配了 10 个字节。这还会导致不希望的输出。

    内存泄漏

    内存泄漏可能真正令人讨厌。下面的列表描述了一些导致内存泄漏的场景。

    • 重新赋值

      我将使用一个示例来说明重新赋值问题。

    char *memoryArea = malloc(10);
    char *newArea = malloc(10);

    这向如下面的图 4 所示的内存位置赋值。

    图 4. 内存位置

    memoryArea 和 newArea 分别被分配了 10 个字节,它们各自的内容如图 4 所示。如果某人执行如下所示的语句(指针重新赋值)……

    memoryArea = newArea;

    则它肯定会在该模块开发的后续阶段给您带来麻烦。

    在上面的代码语句中,开发人员将 memoryArea 指针赋值给 newArea 指针。结果,memoryArea 以前所指向的内存位置变成了孤立的,如下面的图 5 所示。它无法释放,因为没有指向该位置的引用。这会导致 10 个字节的内存泄漏。

    图 5. 内存泄漏

    在对指针赋值前,请确保内存位置不会变为孤立的。

    • 首先释放父块

      假设有一个指针 memoryArea,它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置,如图 6所示。

    如果通过调用 free 来释放了 memoryArea,则 newArea 指针也会因此而变得无效。newArea 以前所指向的内存位置无法释放,因为已经没有指向该位置的指针。换句话说,newArea 所指向的内存位置变为了孤立的,从而导致了内存泄漏。

    每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(在此例中为 newArea),并从那里开始释放,然后再遍历回父节点。

    这里的正确实现应该为:

    free( memoryArea->newArea);
    free(memoryArea);
    • 返回值的不正确处理

      有时,某些函数会返回对动态分配的内存的引用。跟踪该内存位置并正确地处理它就成为了 calling 函数的职责。

      char *func( )
      {
          return malloc(20); // make sure to memset this location to ‘\0’…
      }
      void callingFunc( )
      {
          func ( ); // Problem lies here
      }

      在上面的示例中,callingFunc() 函数中对 func() 函数的调用未处理该内存位置的返回地址。结果,func() 函数所分配的 20 个字节的块就丢失了,并导致了内存泄漏。

    归还您所获得的

    在开发组件时,可能存在大量的动态内存分配。您可能会忘了跟踪所有指针(指向这些内存位置),并且某些内存段没有释放,还保持分配给该程序。

    始终要跟踪所有内存分配,并在任何适当的时候释放它们。事实上,可以开发某种机制来跟踪这些分配,比如在链表节点本身中保留一个计数器(但您还必须考虑该机制的额外开销)。

    访问空指针

    访问空指针是非常危险的,因为它可能使您的程序崩溃。始终要确保您不是 在访问空指针。

    总结

    本文讨论了几种在使用动态内存分配时可以避免的陷阱。要避免内存相关的问题,良好的实践是:

    • 始终结合使用 memset 和 malloc,或始终使用 calloc
    • 每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
    • 在对指针赋值前,要确保没有内存位置会变为孤立的。
    • 每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应首先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
    • 始终正确处理返回动态分配的内存引用的函数返回值。
    • 每个 malloc 都要有一个对应的 free。
    • 确保您不是在访问空指针。
    展开全文
  • Java内存泄漏引起的原因: 内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为... 造成内存泄漏几种情况:1、静态集合类引起内存泄漏 像HashM...
  • 检测内存泄漏的关键是要能截获住对分配内存和释放内存的函数的调用。截获住这两个函数,我们就能跟踪每一块内存的生命周期,比如,每当成功的分配一块内存后,就把它的指针加入一个全局的list中;每当释放一块内存,...
  • 最近朋友推荐了一篇关于内存溢出与内存泄漏的文章,感觉写的还不错,于是便在网上搜索了一番,对这块进行了加固,发现自己之前写的代码也存在一些内存泄漏的风险,所以弄懂内存泄漏与内存溢出是很有利于我们提高代码...
  • 几种内存泄露

    2017-04-10 12:48:50
    碰到的内存泄露无非有以下几种:  (1) 堆内存泄漏(Heap leak)。堆内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果...
  • 一....内存泄露 (memory leak),是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致oom!
  • Java内存泄漏引起的原因:  内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。...造成内存泄漏几种情况: 1、静态集合类引起内存...
  • Java内存泄漏引起的原因:  内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。...造成内存泄漏几种情况: 1、静态集合类引起内存...
  • 导致JS内存泄漏几种情况

    千次阅读 2017-08-07 14:32:57
    内存泄漏是开发中很常见的问题,即使使用具有自动管理内存的语言,也有可能出现内存泄漏的情况,内存泄漏可能会引起变慢、延迟、崩溃等问题。要解决内存泄漏问题,首先要弄懂什么是内存泄漏,什么情况下会导致内存...
  • 内存泄漏几种情况

    2019-06-21 16:44:58
    内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏内存泄漏形象的...
  • Android 引起内存泄漏几种情况

    千次阅读 2020-12-11 18:01:38
    内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会...
  • js内存泄露几种情况

    万次阅读 2014-05-07 15:18:32
    想解决内存泄露问题,必须知道什么是内存泄露,什么情况下出现内存泄露,才能在遇到问题时,逐个排除。这里只讨论那些不经意间的内存泄露。 一、什么是内存泄露 内存泄露是指一块被分配的内存既不能使用,又不...
  • C++内存泄漏几种情况

    千次阅读 2017-10-08 12:43:33
    情况下会出现这种内存泄露:一是在堆里创建了对象占用了内存,但是没有显示地释放对象占用的内存;二是在类的构造函数中动态的分配了内存,但是在析构函数中没有释放内存或者没有正确的释放内存
  • 老生常谈的几种循环引用造成的内存泄漏问题。1 Block和delegate2 timer的使用另外几种内存泄漏的情况。1 非OC对象内存处理在ARC下,只对OC对象进行了自动化管理。但对于非OC对象仍然需要手动释放CGImageRef类型变量...
  • 可能出现内存泄漏几种情况

    千次阅读 2017-04-05 23:04:05
    定义    简单来说,内存泄漏就是程序在申请一个内存空间后没有释放,直到程序运行结束后才释放。这样看起来似乎没什么大问题,但是如果程序会持续运行很长时间...   内存泄漏可能发生在如下几种条件下:    1
  • c++中内存泄漏几种情况 1. 在类的构造函数和析构函数中没有匹配的调用new和delete函数 两种情况下会出现这种内存泄露:一是在堆里创建了对象占用了内存,但是没有显示地释放对象占用的内存;二是在类的构造函数中...
  • 情况下会出现这种内存泄露:一是在堆里创建了对象占用了内存,但是没有显示地释放对象占用的内存;二是在类的构造函数中动态的分配了内存,但是在析构函数中没有释放内存或者没有正确的释放内存 2. 没有正确地...
  • C语言中申请内存几种方式

    千次阅读 2018-09-19 15:00:48
    一、C语言跟内存分配方式 &lt;1&gt;从静态存储区域分配. 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量、static变量.&lt;2&gt;在栈上创建在执行函数时,...
  • iOS 内存泄漏几种原因

    千次阅读 2018-11-27 22:43:08
    CGImageRef类型变量非OC对象,其需要手动执行释放操作CGImageRelease(ref),否则会造成大量的内存泄漏导致程序崩溃。其他的对于CoreFoundation框架下的某些对象或变量需要手动释放、C语言代码中的malloc等需要对应...
  • Android导致内存泄漏几种情形

    千次阅读 2016-06-14 10:19:41
    集合类 集合类如果仅仅有添加元素的方法,而没有相应的删除...不正确使用单例模式是引起内存泄漏的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的
  • ARC下导致内存泄露几种情况

    千次阅读 2016-02-17 17:53:03
    IOS的ARC会导致的内存泄露问题和...下面列举两ARC导致内存泄露的情况。 1,循环参照 A有个属性参照B,B有个属性参照A,如果都是strong参照的话,两个对象都无法释放。 这种问题常发生于把delegate声明为stro

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 142,604
精华内容 57,041
关键字:

内存泄漏几种方式