精华内容
下载资源
问答
  • 内存泄漏和检测方式

    2020-09-16 15:30:15
    内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存情况。内存泄漏并非指内存在物理上消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存控制,从而造成...

    内存泄漏和后果

      

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

    最难捉摸也最难检测到的错误之一是内存泄漏,即未能正确释放以前分配的内存的 bug。 只发生一次的小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆:从性能不良(并且逐渐降低)到内存完全用尽。 更糟的是,泄漏的程序可能会用掉太多内存,以致另一个程序失败,而使用户无从查找问题的真正根源。 此外,即使无害的内存泄漏也可能是其他问题的征兆。

    内存泄漏会因为减少可用内存的数量从而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉导致全部或部分设备停止正常工作,或者应用程序崩溃。内存泄漏可能不严重,甚至能够被常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。

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

    Windows平台下的内存泄漏检测

     

        检测     

     Windows平台下面Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法,原理大致如下:内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录,程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。在vs中启用内存检测的方法如下:

          

    • STEP1,在程序中包括以下语句: (#include 语句必须采用上文所示顺序。 如果更改了顺序,所使用的函数可能无法正常工作。)
    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>

     

    通过包括 crtdbg.h,将 malloc 和 free 函数映射到它们的调试版本,即 _malloc_dbg 和 _free_dbg,这两个函数将跟踪内存分配和释放。 此映射只在调试版本(在其中定义了_DEBUG)中发生。 发布版本使用普通的 malloc 和 free 函数。

    #define 语句将 CRT 堆函数的基版本映射到对应的“Debug”版本。 并非绝对需要该语句;但如果没有该语句,内存泄漏转储包含的有用信息将较少。

    • STEP2, 在添加了上述语句之后,可以通过在程序中包括以下语句(通常应恰好放在程序退出位置之前)来转储内存泄漏信息:
    	
    _CrtDumpMemoryLeaks();

     完整的Deme

    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
     
    #include <iostream>
    using namespace std;
     
    void GetMemory(char *p, int num)
    {
        p = (char*)malloc(sizeof(char) * num);
    }
     
    int main(int argc,char** argv)
    {
        char *str = NULL;
        GetMemory(str, 100);
        cout<<"Memory leak test!"<<endl;
        _CrtDumpMemoryLeaks();
        return 0;
    }

    当在调试器下运行程序时,_CrtDumpMemoryLeaks 将在“输出”窗口中显示内存泄漏信息。 内存泄漏信息如下所示: 

    如果没有使用 #define _CRTDBG_MAP_ALLOC 语句,内存泄漏转储将如下所示: 

    未定义 _CRTDBG_MAP_ALLOC 时,所显示的会是:

    • 内存分配编号(在大括号内)。

    • 块类型(普通、客户端或 CRT)。

     

    从不会在内存泄漏信息中看到下面两种块类型:

     

     

    1. “普通块”是由程序分配的普通内存。

    2. “客户端块”是由 MFC 程序用于需要析构函数的对象的特殊类型内存块。 MFC new 操作根据正在创建的对象的需要创建普通块或客户端块。

    3. “可用块”是已释放的内存块。

    4. “忽略块”是您已特别标记的块,因而不出现在内存泄漏报告中。

    5. “CRT 块”是由 CRT 库为自己使用而分配的内存块。 CRT 库处理这些块的释放,因此您不大可能在内存泄漏报告中看到这些块,除非出现严重错误(例如 CRT 库损坏)。 

    • 十六进制形式的内存位置。

    • 以字节为单位的块大小。

    • 前 16 字节的内容(亦为十六进制)。

    定义了 _CRTDBG_MAP_ALLOC 时,还会显示在其中分配泄漏的内存的文件。 文件名后括号中的数字(本示例中为 10)是该文件中的行号。

    注意:如果程序总是在同一位置退出,调用 _CrtDumpMemoryLeaks 将非常容易。 如果程序从多个位置退出,则无需在每个可能退出的位置放置对 _CrtDumpMemoryLeaks 的调用,而可以在程序开始处包含以下调用:

    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    该语句在程序退出时自动调用 _CrtDumpMemoryLeaks。 必须同时设置 _CRTDBG_ALLOC_MEM_DF 和 _CRTDBG_LEAK_CHECK_DF 两个位域,如前面所示。 

     

    定位具体的内存泄漏地方 

        通过上面的方法,我们几乎可以定位到是哪个地方调用内存分配函数malloc和new等,如上例中的GetMemory函数中,即第10行!但是不能定位到,在哪个地方调用GetMemory()导致的内存泄漏,而且在大型项目中可能有很多处调用GetMemory。如何要定位到在哪个地方调用GetMemory导致的内存泄漏?

         定位内存泄漏的另一种技术涉及在关键点对应用程序的内存状态拍快照。 CRT 库提供一种结构类型 _CrtMemState,您可用它存储内存状态的快照:  

    	
    _CrtMemState s1, s2, s3;

    若要在给定点对内存状态拍快照,请向 _CrtMemCheckpoint 函数传递 _CrtMemState 结构。 该函数用当前内存状态的快照填充此结构:

    	
    _CrtMemCheckpoint( &s1 );

    通过向 _CrtMemDumpStatistics 函数传递 _CrtMemState 结构,可以在任意点转储该结构的内容:

    	
    _CrtMemDumpStatistics( &s1 );

    若要确定代码中某一部分是否发生了内存泄漏,可以在该部分之前和之后对内存状态拍快照,然后使用 _CrtMemDifference 比较这两个状态:

    _CrtMemCheckpoint( &s1 );
    // memory allocations take place here
    _CrtMemCheckpoint( &s2 );
     
    if ( _CrtMemDifference( &s3, &s1, &s2) )
       _CrtMemDumpStatistics( &s3 );

          顾名思义,_CrtMemDifference 比较两个内存状态(s1 和 s2),生成这两个状态之间差异的结果(s3)。 在程序的开始和结尾放置 _CrtMemCheckpoint 调用,并使用_CrtMemDifference 比较结果,是检查内存泄漏的另一种方法。 如果检测到泄漏,则可以使用 _CrtMemCheckpoint 调用通过二进制搜索技术来划分程序和定位泄漏。

    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
     
    #include <iostream>
    using namespace std;
     
    _CrtMemState s1, s2, s3;
     
    void GetMemory(char *p, int num)
    {
        p = (char*)malloc(sizeof(char) * num);
    }
     
    int main(int argc,char** argv)
    {
        _CrtMemCheckpoint( &s1 );
        char *str = NULL;
        GetMemory(str, 100);
        _CrtMemCheckpoint( &s2 );
        if ( _CrtMemDifference( &s3, &s1, &s2) )
            _CrtMemDumpStatistics( &s3 );
        cout<<"Memory leak test!"<<endl;
        _CrtDumpMemoryLeaks();
        return 0;
    }

    输出为:

    这说明在s1和s2之间存在内存泄漏!!!如果GetMemory不是在s1和s2之间调用,那么就不会有信息输出。 

    Linux平台下的内存泄漏检测

     

    在上面我们介绍了,vs中在代码中“包含crtdbg.h,将 malloc 和 free 函数映射到它们的调试版本,即 _malloc_dbg 和 _free_dbg,这两个函数将跟踪内存分配和释放。 此映射只在调试版本(在其中定义了_DEBUG)中发生。 发布版本使用普通的 malloc 和 free 函数。”即为malloc和free做了钩子,用于记录内存分配信息。

    Linux下面也有原理相同的方法——mtrace,http://en.wikipedia.org/wiki/Mtrace。方法类似,我这就不具体描述,参加给出的链接。这节我主要介绍一个非常强大的工具valgrind。如下图所示:

    ==6118== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==6118==    at 0x4024F20: malloc (vg_replace_malloc.c:236)
    ==6118==    by 0x8048724: GetMemory(char*, int) (in /home/netsky/workspace/a.out)
    ==6118==    by 0x804874E: main (in /home/netsky/workspace/a.out) 

    • Things to notice:
      • There is a lot of information in each error message; read it carefully.
      • The 6118 is the process ID; it’s usually unimportant.
      • The first line ("Heap Summary") tells you what kind of error it is.
      • Below the first line is a stack trace telling you where the problem occurred. Stack traces can get quite large, and be
      confusing, especially if you are using the C++ STL. Reading them from the bottom up can help.

      • The code addresses (eg. 0x4024F20) are usually unimportant, but occasionally crucial for tracking down weirder
      bugs.

      The stack trace tells you where the leaked memory was allocated. Memcheck cannot tell you why the memory leaked,
      unfortunately. (Ignore the "vg_replace_malloc.c", that’s an implementation detail.)
      There are several kinds of leaks; the two most important categories are:
      • "definitely lost": your program is leaking memory -- fix it!
      • "probably lost": your program is leaking memory, unless you’re doing funny things with pointers (such as moving
      them to point to the middle of a heap block)

    Valgrind的使用请见手册http://valgrind.org/docs/manual/manual.html

    总结

    其实内存泄漏的原因可以概括为:调用了malloc/new等内存申请的操作,但缺少了对应的free/delete,总之就是,malloc/new比free/delete的数量多。我们在编程时需要注意这点,保证每个malloc都有对应的free,每个new都有对应的deleted!!!平时要养成这样一个好的习惯。

    要避免内存泄漏可以总结为以下几点:

    • 程序员要养成良好习惯,保证malloc/new和free/delete匹配;
    • 检测内存泄漏的关键原理就是,检查malloc/new和free/delete是否匹配,一些工具也就是这个原理。要做到这点,就是利用宏或者钩子,在用户程序与运行库之间加了一层,用于记录内存分配情况。

     

    转载:出处:http://www.cnblogs.com/skynet/

    展开全文
  • 内存泄漏和内存溢出区别与解决方式

    万次阅读 多人点赞 2018-07-20 08:19:25
    内存泄漏(memory leak ) 内存...我们知道了内存泄漏的原因而内存溢出则有可能是因为我们我们多次内存泄漏堆积后的后果则变成了内存溢出 内存溢出: 指程序申请内存时,没有足够的内存供申请者使用,或者说,给了...

    内存泄漏(memory leak ) 内存溢出 (out of memory)

    内存泄露 :是指程序在申请内存后,无法释放已申请的内存空间就造成了内存泄漏,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

    我们知道了内存泄漏的原因而内存溢出则有可能是因为我们我们多次内存泄漏堆积后的后果则变成了内存溢出

    内存溢出: 指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出,简单来说就是自己所需要使用的空间比我们拥有的内存大内存不够使用所造成的内存溢出。

    内存泄漏的分类(按发生方式来分类)

    1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
    2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
    3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
    4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

    内存泄漏的解决方法:

    1. 内存泄漏也许是因为活动已经被使用完毕,但是仍然在其他地方被引用,导致无法对其进行回收。我们只需要给对活动进行引用的类独立出来或者将其变为静态类,该类随着活动的结束而结束,也就没有了当活动结束但仍然还被其他类引用的情况。
    2. 资源性对象在不使用的时候,应该调用它的close()函数将其关闭掉。。
    3. 集合容器中的内存泄露 ,我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
      需要在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。

    4. WebView造成的泄露,当我们不使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。
      我们应该为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

    内存溢出的原因及解决方法:

    1. 内存溢出原因:
      1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
      2.集合类中有对对象的引用,使用完后未清空,产生了堆积,使得JVM不能回收;
      3.代码中存在死循环或循环产生过多重复的对象实体;
      4.使用的第三方软件中的BUG;
      5.启动参数内存值设定的过小
    2. 内存溢出的解决方案:
      第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)

      第二步,检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。

      第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

    重点排查以下几点:
    1.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

    2.检查代码中是否有死循环或递归调用。

    3.检查是否有大循环重复产生新对象实体。

    4.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

    第四步,使用内存查看工具动态查看内存使用情况

     

    如何避免内存泄漏?

    1、在涉及使用Context时,对于生命周期比Activity长的对象应该使用Application的Context。凡是使用Context优先考虑Application的Context,当然它并不是万能的,对于有些地方则必须使用Activity的Context。对于Application,Service,Activity三者的Context的应用场景如下:

     

     

    其中,NO1表示Application和Service可以启动一个Activity,不过需要创建一个新的task任务队列。而对于Dialog而言,只有在Activity中才能创建。除此之外三者都可以使用。

    2、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏。
    3、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null。
    4、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期。
    5、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
    1将内部类改为静态内部类
    2静态内部类中使用弱引用来引用外部类的成员变量

    如何检查和分析内存泄漏?

    因为内存泄漏是在堆内存中,所以对我们来说并不是可见的。通常我们可以借助MAT、LeakCanary等工具来检测应用程序是否存在内存泄漏。
    1、MAT是一款强大的内存分析工具,功能繁多而复杂。
    2、LeakCanary则是由Square开源的一款轻量级的第三方内存泄漏检测工具,当检测到程序中产生内存泄漏时,它将以最直观的方式告诉我们哪里产生了内存泄漏和导致谁泄漏了而不能被回收。

     

     

     

    程序有始有终,我们负责创造它,也需要负责将它销毁。

    展开全文
  • 内存泄漏(memory leak ) 内存...我们知道了内存泄漏的原因而内存溢出则有可能是因为我们我们多次内存泄漏堆积后的后果则变成了内存溢出 内存溢出: 指程序申请内存时,没有足够的内存供申请者使用,或者说,给了...

    内存泄漏(memory leak ) 内存溢出 (out of memory)


    内存泄露 :是指程序在申请内存后,无法释放已申请的内存空间就造成了内存泄漏,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

    我们知道了内存泄漏的原因而内存溢出则有可能是因为我们我们多次内存泄漏堆积后的后果则变成了内存溢出

    内存溢出: 指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出,简单来说就是自己所需要使用的空间比我们拥有的内存大内存不够使用所造成的内存溢出。

    内存泄漏的分类(按发生方式来分类)

    常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
    偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
    一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
    隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
    内存泄漏的解决方法:

    内存泄漏也许是因为活动已经被使用完毕,但是仍然在其他地方被引用,导致无法对其进行回收。我们只需要给对活动进行引用的类独立出来或者将其变为静态类,该类随着活动的结束而结束,也就没有了当活动结束但仍然还被其他类引用的情况。
    资源性对象在不使用的时候,应该调用它的close()函数将其关闭掉。。
    集合容器中的内存泄露 ,我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
    需要在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。

    WebView造成的泄露,当我们不使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。
    我们应该为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

    内存溢出的原因及解决方法:

    内存溢出原因:
    1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
    2.集合类中有对对象的引用,使用完后未清空,产生了堆积,使得JVM不能回收;
    3.代码中存在死循环或循环产生过多重复的对象实体;
    4.使用的第三方软件中的BUG;
    5.启动参数内存值设定的过小
    内存溢出的解决方案:
    第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)

    第二步,检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。

    第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

    重点排查以下几点:
    1.检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

    2.检查代码中是否有死循环或递归调用。

    3.检查是否有大循环重复产生新对象实体。

    4.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

    第四步,使用内存查看工具动态查看内存使用情况

     

    如何避免内存泄漏?
    1、在涉及使用Context时,对于生命周期比Activity长的对象应该使用Application的Context。凡是使用Context优先考虑Application的Context,当然它并不是万能的,对于有些地方则必须使用Activity的Context。对于Application,Service,Activity三者的Context的应用场景如下:

     

     

    其中,NO1表示Application和Service可以启动一个Activity,不过需要创建一个新的task任务队列。而对于Dialog而言,只有在Activity中才能创建。除此之外三者都可以使用。

    2、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏。
    3、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null。
    4、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期。
    5、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
    1将内部类改为静态内部类
    2静态内部类中使用弱引用来引用外部类的成员变量

    如何检查和分析内存泄漏?
    因为内存泄漏是在堆内存中,所以对我们来说并不是可见的。通常我们可以借助MAT、LeakCanary等工具来检测应用程序是否存在内存泄漏。
    1、MAT是一款强大的内存分析工具,功能繁多而复杂。
    2、LeakCanary则是由Square开源的一款轻量级的第三方内存泄漏检测工具,当检测到程序中产生内存泄漏时,它将以最直观的方式告诉我们哪里产生了内存泄漏和导致谁泄漏了而不能被回收。

     

     

     

    程序有始有终,我们负责创造它,也需要负责将它销毁。
    --------------------- 
    作者:白木棉 
    来源:CSDN 
    原文:https://blog.csdn.net/jie1175623465/article/details/81121548 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • JS内存泄漏

    2020-05-10 17:17:52
    一、闭包定义 ...三、造成内存泄露的方式 1、意外全局变量引起内存泄露 例:函数中没有使用var声明变量 2、闭包引起的内存泄漏 例:function fn1(){ var n=1; function fn2(){//在加一个fn2...

    一、闭包的定义
    当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
    二、闭包的特点
    ①函数嵌套函数
    ②函数内部可以引用函数外部的参数和变量
    ③参数和变量不会被垃圾回收机制回收
    三、造成内存泄露的方式
      1、意外的全局变量引起的内存泄露
         例:函数中没有使用var声明的变量
      2、闭包引起的内存泄漏
         例:function fn1(){
                var n=1;
                function fn2(){//在加一个fn2当他的子集
                     alert(n);
                }
                return fn2(); 
                //return出来后 他就给 window了所以一直存在内存中。
             }
             fn1();
       3、定时器setTimeout和setInterval没有被清除掉
          clearTimeout/clearInterval
       4、死循环
          例:while(1){ a++; } 
       5、给DOM对象添加的属性是一个对象的引用
          例:var obj = {};
             document.getElementById('id').property = obj;
             // 如果DOM不被删除则obj会一直存在
       6、没有清理的DOM元素引用
          例:var refA = document.getElementById('refA');
             document.body.removeChild(refA);
             // #refA不能回收,因为有变量refA的引用,可以使用refA=null;
       7、给DOM对象用attachEvent绑定事件(记得detachEvent)
          例:function f(){}
             element.attachEvent("onclock",f);
       8、循环引用
    四、JS垃圾回收机制(GC原理)
       JS具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。
    五、JS垃圾回收方式:
       1、标记清除:当变量进入环境时,将这个变量标记为“进入环境”,当变量离开环境时,则将其标记为“离开环境”。
                  标记“离开环境”的就回收内存。
       2、引用计数:跟踪记录每个值被引用的次数,当引用次数为0时,垃圾收集器下一次运行的时候,它就会释放
                 引用次数为0的变量

    一、循环引用:
    循环引用指的是对象A 中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。
    例:function problem(){
               var objectA = new Object();
               var objectB = new Object();
               objectA.b = objectB;
               objectB.a = objectA;
          }

    展开全文
  • 造成内存泄漏典型场景: 1.单例模式不正确使用单例对象在初始化后将在JVM整个生命周期中以静态变量的方式存在。如果单例对象持有对外部对象引用,那么这个对象将不能被JVM正常回收 2.数据库、网络、IO连接没有...
  • 单例造成的内存泄露 单例静态特性导致其生命周期同应用一样长。 解决方案: 将该属性引用方式改为弱引用; 如果传入Context,使用ApplicationContext; 2. InnerClass匿名内部类 在Java中,非静态...
  • Java内存泄露

    2011-12-02 00:38:50
    对其有了更进一步了解,一直以为JAVA有了内存回收,不用程序员去关心了,不会内存泄漏了,可是正是因为JAVA给我们这一个美好承诺,使我们在写程序时忽略了一些问题,一样造成内存泄漏,导致程序性能下降。...
  • 在UIImage处理中,时常会使用到drawInRect方法,但是缺点是内存占用过大,且造成内存泄漏无法回收。这一点是因为对象持有,导致不能及时释放原因。 多调用几次这个方法,内存就暴增。 所以,目前我采用的方式是,...
  • Go语言内存回收机制GC

    2020-07-16 17:37:02
    所谓内存回收,便是指当前内存使用完毕,释放当前存储器,以供后续继续使用,如果没有进行及时释放,则会造成内存泄漏 常见GC方式有如下三种 引用计数:对每一个对象维护一个引用计数,当引用该对象对象被...
  • 介绍闭包及闭包的应用场景 #闭包的特性 1.函数嵌套函数 2.函数内部可以引用外部的参数和...3.缺点常驻内存,会增大内存的使用量,使用不当造成内存泄漏 #为什么要使用闭包 1.想要得到函数内部的局部变量 ...
  • 造成程序出错和内存泄漏。 有大佬知道如何解决或改进这个问题吗? 附测试代码: <code class="language-python">from multiprocessing import shared_memory import multiprocessing as mp import ...
  • 使用深拷贝可以保证堆区开辟数据不会被析构函数重复释放多次而造成内存泄漏使用深拷贝需要注意什么? 使用深拷贝时,如果指针不为NULL(构造函数已经将变量初始化),就应该先将指针置为空,再做深拷贝操作。 ...
  • v8

    2017-03-06 19:12:00
    如果是自己设计内存当缓存使用,即用对象的方式缓存数据,.v8垃圾回收机制则不会回收这些缓存,因此推荐使用上面模块,以防止造成内存泄漏. 转载于:https://www.cnblogs.com/jay--zhang/p/6511470.html...
  • STL容器中既可以存储对象,也可以存储指针,这里分析一下利弊,和使用注意事项。... 如果存放指针,指针会被复制,对象不会复制,但是存放指针容易造成内存泄漏,原因是,如果某个方法new...
  • 对内存来说,如果只分配而不释放,就会造成内存泄漏,甚至会耗尽内存。所以,在应用程序用完内存后,还需要调用 free() 或 unmap() ,来释放这些不用内存当然,系统也不会任由某个进程用完所有内存。在发现内存...
  • 1、闭包 闭包就是能够读取到其他函数内部变量的函数 闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是...缺点是闭包会一直在内存中,会增大内存的使用量,使用不合理是容易造成内存泄漏。在
  • 性能调优步骤

    2021-02-19 10:38:59
    确认测试脚本没有性能问题,不会造成结果统计不准确,检查内存使用情况,确认并发内存泄漏风险,不会造成结果统计不准确 第四步:判断负载机是否有性能问题,排除负载机性能问题,确保测试结果可参考 第五步:...
  •  ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,...
  • JS学习之——闭包

    2021-01-05 23:56:13
    什么是闭包? 闭包就是 能够读取其他函数内部变量函数 闭包是指有权访问另一个函数作用域中变量函数 创建闭包最常见的方式...缺点是闭包会常驻内存,会增大内存使用量,使用不当,很容易造成泄漏 在js中,函数即
  • ref/unref应该返回什么值

    千次阅读 2008-05-21 08:04:00
    转载时请注明出处和作者联系方式作者联系方式:李先静 引用计数是追踪对象生命周期最常用方法,一方面保证对象在有人使用不会被销毁,另外一方面又保证不会因为忘记销毁对象而造成内存泄漏。具有引用计数功能...
  • 【C++11】weak_ptr

    2021-04-25 19:05:03
    weak_ptr处理shared_ptr中因使用不当造成的内存泄漏问题 a. 同一原始地址不能初始化多个共享智能指针 b. 函数不能返回管理了this共享智能指针对象 c. 共享智能指针不能嵌套循环引用 表示方式 弱指针初始化 ...
  • 内存泄漏优化;线程优化;Bitmap优化;网络优化;懒加载优化,启动页优化;静态变量优化;电量性能优化;view控件异常销毁保存重要信息优化;去除淡黄色警告优化;使用注解替代枚举优化;glide加速优化;多渠道打包...
  • 指针的使用具有很强的技巧性和灵活性,但同时也带来了很大的危险性。在XXX的代码中有如下一端对指针的灵活使用: ... ... _UC *puc_card_config_tab; ... ... Get_Config_Table( AMP_CPM_CARD_CONFIG_TABLE, ...
  • 零起点学通C++多媒体范例教学代码

    热门讨论 2010-11-30 09:35:13
    8.4.1 内存泄漏 8.4.2 在堆中创建对象 8.4.3 在堆中删除对象 8.4.4 访问堆中数据成员 8.4..5 在构造函数中开辟内存空间 8.4.6 对象在栈与堆中不同 8.5 this指针 8.6 指针常见错误 8.7 指针运算 8.7.1 指针加...
  • 8.4.1 内存泄漏 8.4.2 在堆中创建对象 8.4.3 在堆中删除对象 8.4.4 访问堆中数据成员 8.4..5 在构造函数中开辟内存空间 8.4.6 对象在栈与堆中不同 8.5 this指针 8.6 指针常见错误 8.7 指针运算 8.7.1...
  • java 面试题 总结

    2009-09-16 08:45:34
    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector...

空空如也

空空如也

1 2 3
收藏数 41
精华内容 16
关键字:

不会造成内存泄漏的使用方式