跳转至

程序内存问题处置方法

什么是内存泄漏

在Linux中,一个程序的运行内存由两部分组成,一部分是栈,一部分是堆。栈是由系统自动分配和释放的,而堆是由程序员自己分配和释放的。当程序员分配了一块内存,但是没有释放,这块内存就会一直被程序占用,而无法被其他程序使用,这就是内存泄漏。

内存泄漏的出现并不会直接导致程序崩溃,因此很难被发现。但是随着程序运行时间的增加,内存泄漏会越来越严重,最终导致程序崩溃。

内存泄漏应当竭尽所能的避免,我建议应当在研发阶段就尽可能的避免内存泄漏的出现,而不是等到程序出现内存泄漏后再去修复。但内存泄漏很难通过约束、规范来避免,因此我们需要在程序运行时检测内存泄漏。

内存泄漏的检测方法,这里我们用两种方式来讲解:

  • 工具
  • 代码

工具

Valgrind

安装

使用

valgrind valgrind --leak-check=full --show-leak-kinds=all ./your-program arg1 arg2

FAQ

1. 用valgrind运行程序时,如果程序中设置了RLIMIT_NOFILE会出错。

解决方案:

  1. valgrind运行程序时,需要添加环境变量XXX_RUNNING_ON_VALGRIND,比如:
XXX_RUNNING_ON_VALGRIND=1 valgrind --leak-check=full --show-leak-kinds=all ./your-program arg1 arg2
  1. 在程序中获取环境变量XXX_RUNNING_ON_VALGRIND,如果存在则不设置RLIMIT_NOFILE

注意:XXX是一个建议前缀,以避免和其他程序冲突,比如在Nginx中可以是NGX_RUNNING_ON_VALGRIND

Gcc Address Sanitizer

代码

进程内存一直增加,直到被OOM杀死,但是没有内存泄漏

Linux内核的内存管理是自动的,并且设计得非常复杂,以应对各种不同的使用情况。通常,你不能直接控制内核什么时候回收内存,内核会根据当前的内存使用情况、页面年龄、访问频率等因素来决定。

然而,Linux提供了一些参数,你可以通过调整这些参数来影响内核的内存管理行为。这些参数主要存在于/proc/sys/vm目录下,你可以通过读写这些文件来查看或更改这些参数。

以下是其中的一些参数:

  1. swappiness:这个参数控制内核更愿意回收哪种页面:文件系统的页面(如缓存和缓冲区)还是进程的匿名页面(如堆和栈)。swappiness=0表示内核将尽可能避免交换进程的匿名页面,而swappiness=100表示内核将更积极地交换进程的匿名页面。

  2. min_free_kbytes:这个参数设置了系统试图保留的最少空闲内存量(以KB为单位)。如果空闲内存低于此值,内核将开始更积极地回收内存。

  3. dirty_background_ratiodirty_ratio:这两个参数影响了内核何时开始将脏页面(即已修改但尚未写入磁盘的页面)写回磁盘。dirty_background_ratio是开始后台写回的阈值,而dirty_ratio是开始主动写回的阈值。

要注意的是,调整这些参数需要小心,因为它们会影响整个系统的性能和稳定性。在生产环境中更改这些设置前,最好在测试环境中进行充分的测试。

另外,对于应用程序来说,一个更直接的方式是尽量避免不必要的内存分配,并及时释放不再使用的内存。你还可以考虑使用更复杂的内存管理策略,如内存池或自定义的内存分配器,以更有效地管理你的程序的内存使用。

评论