6

我有一个 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()其他方式)是否必然会减少物理和虚拟内存的使用?
4

3 回答 3

13

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

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

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

依次回答您的问题:

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

new, malloc, 大数组的静态分配。通常任何需要程序内存的东西。

  • 如果我的任务正在使用虚拟内存,这会不会有问题?

这取决于您的程序的使用模式。如果您分配了从未接触过的大量内存轨道,并且如果您的程序是 64 位程序,那么您使用虚拟内存可能没问题。

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

  • 堆栈和堆函数变量、向量等 - 这些是否必然会增加物理内存的使用?

不一定,但很有可能。触摸变量的行为确保,至少暂时,它(以及“靠近”它的所有内存)都在物理内存中。(顺便说一句:容器之类的std::vector可以分配在堆栈或堆上,但包含的对象是在堆上分配的。)

  • 消除内存泄漏(通过 delete 或 free() 等)是否必然会减少物理和虚拟内存的使用?

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

于 2012-06-05T16:37:10.370 回答
3

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

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

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

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

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

导出 MALLOC_MMAP_THRESHOLD_=8192

导出 MALLOC_ARENA_MAX=4

于 2015-05-08T01:50:58.993 回答