【问题标题】:Memory usage in C++ program, as reported by Gnome resource monitor: confusionC++ 程序中的内存使用情况,由 Gnome 资源监视器报告:混乱
【发布时间】:2014-10-16 15:54:17
【问题描述】:

我正在查看我的应用程序消耗的内存以确保我没有分配太多,并且对 Gnome 资源监视器向我显示的内容感到困惑。我使用以下代码在两个不同的应用程序中分配内存,这些应用程序在其他方面是相同的;它们只包含这段代码和一个 scanf() 调用以在我获取内存使用情况时暂停执行:

malloc(1024 * 1024 * 100);

char* p = new char[1204*1024*100];

下图显示了我的应用在每一行之前和之后的内存使用情况:

现在,我已经阅读了很多(但显然还不够)关于内存使用的内容(包括this SO 问题),并且在区分可写内存和虚拟内存时遇到了麻烦。根据链接的问题,

“可写内存是你的进程拥有的地址空间量 分配写权限”

“虚拟内存是你的应用程序拥有的地址空间 分配”

1) 如果我自己分配了内存,它肯定有写权限吗?

2) 链接的问题还指出(关于 malloc)

"...实际上不会分配任何内存。(请参阅最后的咆哮) malloc(3) 页面的详细信息。)"

我没有看到任何“咆哮”,我的图像显示虚拟内存增加!有人可以解释一下吗?

3)如果我有纯以下代码:

char* p = new char[100];

...资源监视器显示内存和可写内存都增加了 8KB - 与我分配整整一兆字节时相同! - 虚拟内存增加 0.1。这里发生了什么?

4)我应该查看资源监视器中的哪一列来查看我的应用正在使用多少内存?

非常感谢您的参与,如果不清楚或错过任何可能导致我自己找到答案的内容,我们深表歉意。

【问题讨论】:

  • 我不清楚您的问题是否完全重复,所以我没有关闭它。但是您可能缺少的技术术语是“过度使用”。使用[C] overcommit 在 SO 上搜索会显示很多结果。如果您还有更具体的问题,请四处看看,然后回来告诉我们。
  • 那和“延迟分配”或“需求分配”...当您的应用程序“分配”更多内存时,Linux 往往只是将一些额外的虚拟地址空间标记为正在使用,而不实际分配物理内存填充该地址空间 - 当您第一次尝试访问新的虚拟地址时,实际分配会在稍后发生......
  • 好的。我研究了推荐的术语并找到了有用的链接。 This 谈论过度使用,this 有一些示例代码。所以我现在知道为什么我的“可写”列在我触摸我的记忆(通过“memset”)之前不会增加,但我的“虚拟”列会立即增加。但是,我仍然不清楚为什么触摸我的记忆会将其从“虚拟”更改为“可写”。仍然存在的另一个问题是为什么我只为 100 个字符分配了 8KB...
  • 当你分配一小块内存时,内存管理器会分配一个更大的块,然后将它分割成小块返回给你的代码。你可能只是看到了。
  • 触摸内存不会“将其从虚拟变为可写”——这是两个完全不同的特征。进程虚拟地址空间中映射的所有内存都是虚拟的。其中一些是可写的,一些是只读的,一些是可执行的。有些当前由真实的物理内存支持,有些则没有。有些可能已经被调出以交换空间,或者被文件支持等等......而且这一切都以页面大小为增量完成(因此 100 个字符需要 8KB)。

标签: c++ linux memory-management gnome


【解决方案1】:

在 Linux 上了解正在运行的 process 的内存使用情况的更精确方法是使用 proc(5) 文件系统。

所以,如果你的进程 pid 是 1234,试试

cat /proc/1234/maps

请注意,进程的address space 位于virtual memory 中。该地址空间可以由mmap(2) 和其他syscalls(2) 更改。出于几个效率原因malloc(3)free 避免过多地使用这些系统调用,并且更愿意重用以前的free-d 内存区域。因此,当您的程序是 free-ing(或者,在 C++ 中,delete-ing)某个内存块时,该块通常被标记为可重用但不会释放回内核(例如 munmap) .同样,如果您 malloc 仅 100 个字节,则您的 libc 被允许例如使用 mmap 请求一整兆字节(下次您调用 malloc 时,例如 200 字节,它将使用该兆字节的一部分)

另请参阅 http://linuxatemyram.com/Advanced Linux Programming(和 this question 关于内存过量使用)

【讨论】:

  • 感谢巴西尔的评论。然而,虽然这些信息很有用,但它并没有真正回答我的问题(我的意思是从将来有人看这个问题的角度来看)。我希望接受的答案是对我所问内容的参考。我相信你明白:)
【解决方案2】:

Gnome 资源监视器(实际上是绝大多数资源报告工具)报告的内存类别不仅仅是单独的内存类别 - 它们之间存在重叠,因为它们报告的是内存的不同特征。其中一些不同的特征包括:

  • 虚拟与物理 - 现代操作系统上进程地址空间中的所有内存都是虚拟的;虚拟地址空间通过 CPU 的硬件能力映射到实际的物理内存;如何完成映射本身就是一个复杂的话题,不同架构之间存在很多差异
  • 内存访问权限 - 内存可以是可读、可写或可执行的,或三者的任意组合(理论上 - 某些组合实际上没有意义,因此硬件和/或软件实际上可能不允许,但是关键是这些权限是分开处理的)
  • 驻留与非驻留 - 对于虚拟内存系统,由于各种原因,进程的大部分地址空间当前可能实际上并未映射到真实物理内存 - 它可能尚未分配;它可能是二进制文件或库之一的一部分,甚至可能是由于程序尚未调用而尚未加载的数据段;它可能已被换出到交换区域,以便为需要它的其他程序释放物理内存
  • 共享与私有 - 进程虚拟地址空间的只读部分(例如,程序的实际代码和大多数库)可以与使用相同库或程序的其他进程共享 - 这对整体内存使用来说是一个很大的优势,因为运行 37 个不同的 xterm 实例并不意味着 xterm 的代码需要在内存中加载 37 次不同的时间 - 所有进程都可以共享一份代码李>

由于这些以及其他一些因素(IPC 共享内存、内存映射文件、内存区域映射到硬件的物理设备等),决定了任何单个进程使用的实际内存,甚至是整个系统,可能很复杂。

【讨论】:

    猜你喜欢
    • 2016-12-23
    • 2016-08-14
    • 2015-03-23
    • 2020-09-12
    • 1970-01-01
    • 2011-10-11
    • 2019-10-13
    • 1970-01-01
    • 2018-03-22
    相关资源
    最近更新 更多