1.内存溢出和内存泄漏的区别和解决办法
原文链接:https://blog.youkuaiyun.com/qq_33728687/article/details/80577397
内存溢出(out of memory):
指程序在申请内存时,没有足够的内存空间供其使用,出现outofmemory;
内存泄漏(memory leak):
指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,
但内存泄漏堆积后果很严重,无论多少内存,迟早被占光。
以发生的方式来分类,内存泄漏可以分为4类:
1.常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次执行都会导致一块内存泄漏。
2.偶发性内存泄漏。发生内存泄漏只有在某些特定环境或操作过程下才会发生。常发性和偶
发性是相对的。对于特定的环境,偶发性也许变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
3.一次性内存泄漏。发生内存泄漏的代码只会执行一次,由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。
比如在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
4.隐式内存泄漏。程序在运行中不停的分配内存,但是知道结束时在释放内存。严格的说这里并没有发生内存泄漏,
因为最终释放了所有申请的内存。但对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能
导致耗尽系统的所有内存。所以我们称这类内存泄漏为隐式内存泄漏。
----------------------------------------------------------------------------
内存溢出的原因以及解决办法:
1.内存中加载的数据量过于庞大,如一次从数据库中取出过多数据;
2.集合类中有对对象的引用,使用后未清空,是的JVM不能回收;
3.代码中存在死循环或者循环产生过多重复的对象实体;
4.使用第三方软件中的BUG;
5.启动参数内存值设定的过小
内存溢出的解决方案:
1.修改JVM启动参数,直接增加内存。(-Xms,-Xms参数一定不要忘记加)
2.检查错误日志,查看“OutOfMemory”错误前是否有其他异常或错误。
3.对代码进行走查和分析,找出可能发生内存溢出的位置。
重点排查以下几点:
1)检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,
就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库
中数据多了,一次查询就有可能引起内存溢出。对数据库查询尽量采用分页查询。
2)检查代码是否有死循环或递归调用。
3)检查是否有大循环重复产生新对象实体。
4)检查List、Map等集合对象是否有使用后,未清除的问题。List、Map等集合对象
会始终存有对对象的引用,使得这些对象不能被GC回收。
4.使用内存查看工具动态查看内存使用情况。
2. FreeRTOS高级篇7---FreeRTOS内存管理分析
FreeRTOS高级篇7---FreeRTOS内存管理分析_朱工的专栏-优快云博客_freertos 内存管理
3.FreeRTOS 小技巧(二):如何诊断内存泄漏
FreeRTOS 小技巧(二):如何诊断内存泄漏_Zombie's blog-优快云博客
4.如何使用Tracealyzer分析FreeRTOS内存使用情况?
如何使用Tracealyzer分析FreeRTOS内存使用情况? - 知乎
reeRTOS在创建任务、信号量和消息队列等内核对象时支持两种内存分配方式,动态内存和静态内存。当使用动态内存时,任务所需要的内存空间在运行过程中动态申请,当系统heap内存空间不足时任务将会创建失败。
那么如何掌握系统内存的使用情况呢?对于系统内存的使用情况,FreeRTOS提供了如下两个API函数,用户可以在完成系统任务等内核对象的创建工作后调用这些API来了解heap内存的使用情况。
• xPortGetFreeHeapSize()
获取当前未分配的内存堆大小
• xPortGetMinimumEverFreeHeapSize()
获取未分配内存堆的历史最小值,即内存堆的最大使用量
但是上面调用API函数的形式存在如下问题:
1)仅能了解整体的系统内存使用情况,难以针对每个任务进行更细致的分析
2)难以发现可能存在的内存泄露风险,小的内存泄露在长时间的运行后可能导致严重后果
此时可以借助RTOS的可视化分析工具Tracealyzer来更清晰直观的掌握系统内存的使用情况。如何将Tracealyzer添加到项目工程中请参考之前的这篇文章(点击最下方的“阅读原文”)
下面我们将介绍如何使用Tracealyzer来分析系统内存的使用情况。
在演示实验中创建了3个任务,Start_task、Test_task和Led_task。
1、其中Start_task负责创建Test_task和Led_task,并在完成这两个任务的创建工作后将自己删除。
2、在Test_task中,指针变量p和np先分别被分配了200字节的内存,随后指针p被np指针重新赋值,最后调用vPortFree函数释放了np指针所对应的内存空间。
最开始p和np指针分别指向200字节的内存空间,执行p=np后,两个指针均指向了np所对应的内存空间,结果是p之前所指向的内存位置变成了孤立的内存,该内存无法被释放,因为没有指向该内存的指针,从而导致了200字节的内存泄漏。
3、在Led_task中,利用递增变量count多次调用pvPortMalloc函数来演示对内存空间的使用
使用流模式或者快照模式开启Tracealyzer跟踪后,通过views->Memory Heap Utilization打开heap内存跟踪视图。
在Memory Heap Utilization窗口中,横坐标代表时间轴,纵坐标数值代表heap空间使用量,当调用pvPortMalloc函数申请heap空间时,曲线会向上增长,当调用free函数释放空间时,曲线会下降。曲线上的每一个节点对应一次内存申请或者释放操作。双击该节点,可以关联到该操作所对应的函数代码位置。
在Memory Heap Utilization窗口的右侧,会显示系统中存在的任务,不同任务通过不同的颜色来进行区分,用户可以勾选所想要查看的任务:
• 红色曲线代表Test任务,Test任务调用了vPortFree函数释放了np指针所对应的内存空间,但是p指针所对应的内存空间成为了孤立的内存,即发生了内存泄漏。因此在对指针赋值前,需要确保该指针所对应的内存位置不会成为孤立的。
• 绿色曲线代表LED任务,在LED任务中多次调用了pvPortMalloc函数,每次内存空间申请对应曲线上的一个节点。
• 深绿色曲线代表Start任务,Start任务在创建Test和Led任务时需要申请这两个任务所使用的任务堆栈和TCB的空间,对应曲线的4个增长节点。
除了显示每个任务的heap内存使用情况,还可以利用上方的标签切换显示系统整体的heap内存空间使用情况,可以帮助用户了解系统的最大heap使用量在什么时间段,以及系统整体的heap空间增长情况。
如上图所示,系统整体的heap空间在最初阶段达到一个最高点之后回落,随后又随时间不断进行增长直至超过了最开始的最大heap空间使用量。如果系统中存在类似的情况,则可能是存在内存泄漏的问题,随着时间的增长,内存泄漏最终将耗尽heap空间导致系统出错。
当系统中可能存在内存泄漏时,可以通过views->Object History->system heap窗口,通过show Remaining Only选项过滤掉所有已经释放了的内存空间,方便用户迅速定位可能发生内存泄漏的位置。
借助RTOS的可视化分析工具Tracealyzer,用户可以更清晰直观的掌握系统中内存的使用情况,进而开发出更高质量的代码。