内存泄漏专题(2)如何判断程序有内存泄露

简介: 内存泄漏专题(2)如何判断程序有内存泄露

要解决内存泄漏,首先面对的问题就是,如何判断一个程序内存泄露了呢?因为不可能每个内存申请释放的程序都像上面所举的例子那样直观明了。实际上我们面对的程序要比例子复杂千倍万倍。有可能在A函数里申请的内存,在B函数甚至在另外一个.c文件里才会去释放,中间可能经历了无数的if...else,有些分支可能提前return,有些分支又调用了其他的函数,整个系统盘根错节,想靠肉眼去从代码里发现内存泄露的蛛丝马迹,捋明白一块内存的前世今生,简直难于登天。我们不排除有少数基础扎实的资深C语言专家的确有肉眼在代码里察觉到内存泄漏的能力,但对于更多的人来说,这可能并不是一个简单高效的方法。

如果一个程序在运行的过程中,可以看到其占用的内存在不断的增加,尽管有时候增加得很慢,但这时候就千万要小心了,因为你的程序很有可能存在着内存泄漏。

可如果程序比较简单,例如上面的第二段代码,程序一执行就结束了,根本来不及观察内存的变化情况,是无法通过观测正在 运行的程序内存增长情况来判断是否有内存泄漏的。这时候,我们可能要借助一些其他的调试手段或者第三方工具,来判断是否有内存泄漏,比如著名的valgrind,我们将在下一个章节重点介绍。

当然,对于某些引入内存池技术的程序,对于内存泄漏还有另外一层注解。由于内存池具有减少内存碎片,减少与 内核态交互次数等特点,申请和释放都是针对池子而言,不太容易出现内存泄漏,因此被广泛应用于很多企业级的应用程序中。其中,内存池的典型实现,包括定长内存池LOKIBOOST,不定长内存池apr_poolobstack等。

当内存池化之后,由于对于内存的申请和销毁都是先由内存池初始化时向系统申请一块内存,在程序结束时销毁该内存池,中间所有关于内存的操作都是针对池子而言的,因此不太容易出现内存泄漏。但这也并不能彻底解决内存泄漏的隐患。如果某个程序是长期运行的,那么可能申请的内存一直存在于池子中,不会得到销毁,定长内存池相对好一点 ,特别是对于非定长的内存池,如果在程序中一味地从池子中申请内存,但并没有在适当的地方及时归还给池子,同样会造成内存越用越大,导致系统内存耗尽。这种问题相对来说更危险:因为通过valgrind之类的工具是无法排查出来的。

从内存泄漏的现象和危害性来说,我们不难发现:内存泄漏的影响不像 coredump之类有立竿见影的直观影响,它的影响可能是缓慢的,要运行很长一段时间才会出现,可一旦出现,就是非常致命的危险。因此,也很容易知道,对于一个并非长期运行的程序而言 ,可能瞬间就执行完了,即便程序中有内存泄露,但影响却是微乎其微的,因为程序一结束,系统就会将所有内存都回收了。 但即便如此,从良好的代码习惯和代码洁癖的角度来看,仍然是不建议这种情况出现,因为谁也保不准你写的这段代码会被谁复用,从而造成非常严重的事故。

所以大致总结一下,我们判断一个程序是否出现内存泄漏,主要的依据有以下几个方面:

  • 借助第三方工具或hook技术,动态或静态观测内存的申请和释放情况
  • 对于正在运行的程序,可观测内存的增长情况,在数据量级恒定的情况下,如果出现长时间的线性增长,则有可能出现了内存泄漏的情况
  • 梳理代码里申请内存变量的生命周期(俗称人工跑代码),对于比较复杂的程序,要求C语言功底相对较深
  • 基于gperftools之类的pprof观测工具,追踪内存的生命周期

本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对C/C++课程感兴趣的读者,可以点击链接,查看详细的服务:C/C++Linux服务器开发/高级架构师

目录
相关文章
|
3月前
|
NoSQL 测试技术
内存程序崩溃
【10月更文挑战第13天】
148 62
|
1月前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
40 8
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
67 1
|
2月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
2月前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
54 6
|
2月前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
370 9
|
2月前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
3月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
186 22
|
4月前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
|
4月前
|
Java
在 ArkTS 中,如何有效地进行内存管理和避免内存泄漏?
【9月更文挑战第25天】在ArkTS中,有效进行内存管理并避免内存泄漏的方法包括:及时释放不再使用的资源,如关闭监听器和清理定时器;避免循环引用,通过弱引用打破循环;合理使用单例模式,确保单例对象正确释放;及时处理不再使用的页面和组件,在卸载时清理相关资源。
154 9

热门文章

最新文章