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

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

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

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

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

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

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

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

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

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

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

目录
相关文章
|
4月前
|
存储 程序员 C语言
【动态内存管理助力程序优化与性能飞升】(下)
【动态内存管理助力程序优化与性能飞升】
|
4月前
|
C语言
【动态内存管理助力程序优化与性能飞升】(中)
【动态内存管理助力程序优化与性能飞升】
|
22天前
|
存储 编译器 C语言
深入探索C语言动态内存分配:释放你的程序潜力
深入探索C语言动态内存分配:释放你的程序潜力
30 0
|
14天前
|
存储 缓存 监控
Java内存管理:垃圾回收与内存泄漏
【4月更文挑战第16天】本文探讨了Java的内存管理机制,重点在于垃圾回收和内存泄漏。垃圾回收通过标记-清除过程回收无用对象,Java提供了多种GC类型,如Serial、Parallel、CMS和G1。内存泄漏导致内存无法释放,常见原因包括静态集合、监听器、内部类、未关闭资源和缓存。内存泄漏影响性能,可能导致应用崩溃。避免内存泄漏的策略包括代码审查、使用分析工具、合理设计和及时释放资源。理解这些原理对开发高性能Java应用至关重要。
|
29天前
|
缓存 算法 Java
Java内存管理:优化性能和避免内存泄漏的关键技巧
综上所述,通过合适的数据结构选择、资源释放、对象复用、引用管理等技巧,可以优化Java程序的性能并避免内存泄漏问题。
28 5
|
2月前
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
67 1
|
2月前
|
缓存 算法 编译器
C/C++编译器内存优化技术:内存优化关注程序对内存的访问和使用,以提高内存访问速度和减少内存占用。
C/C++编译器内存优化技术:内存优化关注程序对内存的访问和使用,以提高内存访问速度和减少内存占用。
41 0
|
2月前
|
存储 算法 Java
如何使用 Python 管理内存和避免内存泄漏?
如何使用 Python 管理内存和避免内存泄漏?
102 35
|
3月前
|
监控 Java 编译器
优化Go语言程序中的内存使用与垃圾回收性能
【2月更文挑战第5天】本文旨在探讨如何优化Go语言程序中的内存使用和垃圾回收性能。我们将深入了解内存分配策略、垃圾回收机制,并提供一系列实用的优化技巧和建议,帮助开发者更有效地管理内存,减少垃圾回收的开销,从而提升Go程序的性能。
|
4月前
|
存储 程序员 编译器
C/C++程序内存区域划分以及各区域的介绍
C/C++程序内存区域划分以及各区域的介绍