当前位置: 首页 > news >正文

内存泄漏

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存泄漏缺陷具有隐蔽性、积累性的特征,比其他内存非法访问错误更难检测。因为内存泄漏的产生原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷。此外,内存泄漏通常不会直接产生可观察的错误症状,而是逐渐积累,降低系统整体性能,极端的情况下可能使系统崩溃。

以产生的方式来分类,内存泄漏可以分为四类:
1.常发性内存泄漏:发生内存泄漏的代码会被多次执行到,每次被执行时都会导致一块内存泄漏。
2.偶发性内存泄漏:发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
3.一次性内存泄漏:发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅有一块内存发生泄漏。
4.隐式内存泄漏:程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到。

内存泄漏的常见原因
1.显式分配,隐式释放:使用 malloc, calloc, new 等分配了内存,但缺少对应的 free 或 delete。
2.异常处理路径未释放内存:代码中抛出了异常,但在异常捕获处理块中忘记了释放之前申请的内存。
3.数据结构处理错误:例如,从链表或哈希表中移除了节点,但未释放节点占用的内存。
4.循环引用(主要在带有垃圾回收的语言中,如 Java, C#, Python, JS):
对象A持有对象B的引用,对象B也持有对象A的引用。
即使外部已经不再需要A和B,但由于它们互相引用,垃圾回收器(Garbage Collector, GC)会认为它们仍然是“存活”的,从而无法回收它们。
5.静态集合类滥用:使用静态的集合(如 static Map)缓存对象,但从未或者很少清理,导致对象无限增长。
6.监听器和回调未注销:注册了事件监听器或回调函数,但在对象销毁时未及时注销,导致监听器对象无法被回收。
7.资源未关闭:打开了文件、网络连接、数据库连接等,使用后未正确关闭。这些资源通常与内存相关联,也会导致间接的内存泄漏。

如何在测试中发现内存泄漏?
发现内存泄漏不能只靠功能测试,需要进行专门的非功能性测试。
1.手动测试与观察
a) 长时间运行测试:让系统持续运行一个典型业务流程或多个流程组合,模拟真实使用场景。
b) 监控系统资源:使用任务管理器、活动监视器(Mac)等操作系统工具,观察目标进程的内存使用量(如 RSS - 常驻内存集)是否随着时间的推移而持续稳定增长,而不是在一定范围内波动后趋于稳定。
2.使用专业工具进行检测(这是最主要的手段)
例如:Python:
tracemalloc:标准库模块,可以跟踪内存分配的位置。
objgraph:可以可视化对象引用关系,帮助发现循环引用。
memory_profiler:逐行分析内存使用情况。
JavaScript (Node.js):
Chrome DevTools:可以连接到Node.js进程进行内存分析和堆快照对比。
heapdump 模块:可以生成堆转储文件供分析。
Node.js Inspector:内置的调试和分析功能。
3.自动化测试集成

如何预防?
1.良好的编程习惯:遵循“谁分配,谁释放”的原则。
2.代码审查:重点关注资源分配和释放的代码、异常处理分支、静态集合的使用以及监听器的注册/注销。
3.静态代码分析工具:许多IDE和工具(如SonarQube, Coverity, PVS-Studio)可以静态地检测出一些常见的内存泄漏代码模式。
4.将内存测试纳入测试计划:尤其是对于核心和长期运行的服务,必须将内存泄漏测试作为发布标准之一。

内存泄漏是一个“慢性病”,其测试和定位是软件测试中难度较高但至关重要的一环。它要求测试人员不仅要有测试思维,还要具备一定的系统、编程和调试工具使用知识。结合监控、专业工具和自动化流程,可以有效地在软件发布前发现并解决内存泄漏问题,保障软件的长期稳定性和用户体验。

http://www.hskmm.com/?act=detail&tid=12620

相关文章:

  • Context Engineering
  • ios在wifi模式下设置http代理
  • 面试官问:请画出 MySQL 架构图!这种变态问题都能问的出来
  • 基于协方差交叉(CI)的多传感器融合算法matlab仿真,对比单传感器和SCC融合
  • github/网盘/公众号信息收集
  • AtCoder Regular Contest 206 (Div. 2) 部分题解
  • Grafana 和 Openssh 高危漏洞修复
  • 基于双PI控制器和三电平SVPWM交流同步直线电机矢量控制系统的simulink建模与仿真
  • 学习日报(补发)
  • Influxdb 得模糊查询总结
  • 多表关系和多表查询
  • 6
  • 【反比例函数】【做题笔记】【图形存在性】题目合集
  • 20250920 嘉定江桥---江苏吴江区太湖 往返160KM骑行小记
  • 工作队列(Work Queues)与消息确认(Ack)
  • React18新增的hook useId
  • 十年架构演进史:从臃肿war包到云原生,我们终于解放了!
  • week1作业
  • 6-5 汇聚层
  • 从IpadOS 26 Beta版切换成IpadOS 26 正式版
  • 2025.9.21总结
  • 6-4 多输入多输出通道
  • 6-6 卷积神经网络LeNet
  • 5-5读写文件
  • 6-2图像卷积
  • 二叉树的高度和判断平衡二叉树
  • 20250921 之所思 - 人生如梦
  • UE5 Cook数据结构
  • 通过微信对客服系统客户进行消息提醒,比如客户快过期了,访客发来的消息也是通过模板消息通知给客服
  • WPF治具软件模板分享 - Dragonet