虚拟v。评估C / C ++内存泄漏的物理内存

时间:2012-06-05 16:22:24

标签: c++ memory memory-leaks ram virtual-memory

我有一个C ++应用程序,我试图消除内存泄漏,我意识到我不完全理解虚拟和物理内存之间的区别。

来自top的结果(所以16.8g =虚拟,111m =物理):

4406 um 20 0 16.8g 111m 4928 S 64.7 22.8 36:53.65 client

我的进程拥有500个连接,每个用户一个,这些数字意味着每个用户有大约30 MB的虚拟开销。没有进入我的应用程序的细节,这可能听起来远程逼真的唯一方法,将所有向量,结构,线程,函数堆叠在一起,等等,是我不知道虚拟内存实际意味着什么。没有-O优化标志,顺便说一句。

所以我的问题是:

  • C ++中的哪些操作会如此夸大虚拟内存?
  • 如果我的任务是使用虚拟内存演出,这是一个问题吗?
  • 堆栈和堆函数变量,向量等 - 那些必然会增加物理内存的使用吗?
  • 删除内存泄漏(通过deletefree()等)是否必然会减少物理和虚拟内存使用量?

3 个答案:

答案 0 :(得分:7)

虚拟内存是您的程序处理的内容。它由mallocnew等返回的所有地址组成。每个进程都有自己的虚拟地址空间。虚拟地址的使用在理论上受程序地址大小的限制:32位程序有4GB的地址空间; 64位程序有更多。实际上,进程可以分配的虚拟内存量小于这些限制。

物理内存是焊接到主板或安装在内存插槽中的芯片。在任何给定时间使用的物理内存量仅限于计算机中的物理内存量。

虚拟内存子系统将程序使用的虚拟地址映射到CPU发送到RAM芯片的物理地址。在任何特定时刻,大多数分配的虚拟地址都是未映射的;因此物理内存使用低于虚拟内存使用。如果访问已分配但未映射的虚拟地址,操作系统将无形地分配物理内存并将其映射。当您不访问虚拟地址时,操作系统可能会取消映射物理内存。

依次提出问题:

  
      
  • C ++中的哪些操作会使虚拟内存膨胀太多?
  •   

newmalloc,大型数组的静态分配。通常在程序中需要记忆的任何东西。

  
      
  • 如果我的任务是使用虚拟内存演出,这是一个问题吗?
  •   

这取决于程序的使用模式。如果您分配了永远不会触及的大量内存,并且如果您的程序是64位程序,那么您可能正在使用虚拟内存。

此外,如果您的内存使用不受限制地增长,您最终将耗尽某些资源。

  
      
  • 堆栈和堆函数变量,向量等 - 那些必然会增加物理内存的使用吗?
  •   

不一定,但可能。触摸变量的行为确保了(至少暂时)它(以及所有“接近”它的存储器)在物理存储器中。 (旁白:像std::vector这样的容器可以在堆栈或堆上分配,但包含对象在堆上分配。)

  
      
  • 删除内存泄漏(通过删除或free()等)必然会减少物理和虚拟内存使用量吗?
  •   

物理:可能。虚拟:是的。

答案 1 :(得分:3)

虚拟内存是进程使用的地址空间。每个进程都有一个64位(或32位,取决于架构)指针的可寻址字节的完整视图,但不是每个字节映射到真实的东西。操作系统管理将虚拟地址映射到真实物理内存页面的表 - 或者实际上的任何地址(无论它看起来像是应用程序的内存)。例如,对于您的应用程序,地址可能指向某个功能,但实际上它尚未从磁盘加载,并且当您调用它时,它会生成页面错误中断,内核通过从中加载适当的部分来处理可执行文件并将其映射到应用程序的地址空间,因此可以执行。

从Linux的角度来看(我相信大多数现代操作系统):

  • 分配内存会使虚拟内存膨胀。实际上使用分配的内存会增加物理内存使用量。做得太多,它将被交换到磁盘,最终你的进程将被杀死。
  • mmap文件将仅增加虚拟内存使用量,这包括可执行文件的大小:它们越大,使用的虚拟内存就越多。
  • 使用虚拟内存的唯一问题是您可能耗尽了它。它主要是32位系统的一个问题,你只有4GB的内存(1gb是为内核保留的,所以应用程序数据只有3GB)。
  • 在堆栈上分配变量的函数调用可能会增加物理内存使用量,但您(通常)不会泄漏此内存。
  • 分配的堆变量占用虚拟内存,但只有在读取/写入时才会实际获取物理内存。
  • 释放或删除变量并不一定会减少虚拟/物理内存消耗,这取决于分配器内部,但通常会这样做。

答案 2 :(得分:0)

您可以设置以下环境变量来控制malloc的内部内存分配。设置完成后,它将回答所有四个问题。如果您想了解其他选项,请参阅:

http://man7.org/linux/man-pages/man3/mallopt.3.html

导出MALLOC_MMAP_THRESHOLD_ = 8192

导出MALLOC_ARENA_MAX = 4

相关问题