如何定位和处理内存泄漏

对于普通进程来说,能看到的其实是内核提供的虚拟内存,这些虚拟内存通过页表,由系统映射为物理内存。
当进程通过malloc()申请虚拟内存后,系统并不会立即为其分配物理内存,而是首次访问时,才通过缺页异常陷入内核中分配内存。
为了协调CPU与磁盘间的性能差异,Linux还会使用Cache和Buffer,分别把文件和磁盘读写的数据缓存到内存中。
对应用程序来说,动态内存的分配和回收,是既核心又复杂的一个逻辑功能模块。管理内存的过程中,也很容易发生各种各样的“事故”,比如,

  • 没正确回收分配后的内存,导致了泄漏。
  • 访问的是已分配内存边界外的地址,导致程序异常退出,等等。

说起内存泄漏,就要先从内存的分配和回收说起了。

内存的分配和回收

进程的内存空间,分为用户空间和内核空间,用户空间内存包括多个不同的内存段,比如只读段、数据段、堆、栈以及文件映射段等。这些内存段正是应用程序使用内存的基本方式。

举个例子,在程序中定义了一个局部变量,比如一个整数数组 int data[64],就定义了一个可以存储64个整数的内存段。由于这是一个局部变量,它会从内存空间的栈中分配内存。

栈内存由系统自动分配和管理。一旦程序运行超出了这个局部变量的作用域,栈内存就会被系统自动回收,所以不会产生内存泄漏的问题。

再比如,很多时候,我们事先并不知道数据大小,所以就要用到标准库函数malloc()_,在程序中动态分配内存。这时候,系统就会从内存空间的堆中分配内存。

堆内存由应用程序自己来分配和管理。除非程序退出,这些堆内存并不会被系统自动释放,而是需要应用程序明确调用函数free()来释放它们。如果应用程序没有正确释放堆内存,就会造成内存泄漏。

这是两个堆和栈的例子,那么,其他内存段是否也会导致内存泄漏

  • 只读段,包括程序的代码和常量,由于是只读的,不会再去分配新的内存,所以也不会产生内存泄漏。
  • 数据段,包括全局变量和静态变量,这些变量在定义时就已经确定了大小,所以也不会产生内存泄漏。
  • 最后一个内存映射段,包括动态链接库和共享内存,其中共享内存由程序动态分配和管理。所以,如果程序在分配后忘了回收,就会导致跟堆内存类似的泄漏问题。

内存泄漏的危害非常大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把它们再次分配给其他应用。内存泄漏不断累积,甚至会耗尽系统内存。

虽然,系统最终可以通过OOM(Out of Memory)机制杀死进程,但进程在OOM前,可能已经引发了一连串的反应,导致严重的性能问题。

比如,其他需要内存的进程,可能无法分配新的内存;内存不足,又会触发系统的缓存回收以及SWAP机制,从而进一步导致I/O的性能问题等等。

内存泄漏的危害那么大&#

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值