【问题标题】:Memory allocation - How 15 GB can be equal to 2GB?内存分配 - 15 GB 如何等于 2GB?
【发布时间】:2013-08-23 21:03:51
【问题描述】:

我的一个主要应用程序在运行时崩溃。

我想知道这是否与系统的内存分配问题有关。因此,我创建了一个小型测试程序来分配 1GB 的内存并同时运行 15 个这样的进程,因此总共使用了 15GB 的 RAM。

但是,当我运行这个程序时,任务管理器显示它只占用了 2GB 的 RAM?这怎么可能?

我写了一个示例代码如下

char *ptr[1024];
for ( i = 0 ; i < 1024 ; ++i )
{
    ptr[i] = new char[1024 * 1024];
    std::cout << " Allocated 1024 MB" << i << " th time " << std::endl;
}

【问题讨论】:

  • 可能是操作系统过度使用?即,new 返回一个有效指针,尽管内存不足。尝试实际上在获得的内存中写一些东西,你的进程可能会被杀死。
  • 任务管理器不显示“内存占用量”。它显示working sets,这是另一回事。

标签: c++ memory memory-management


【解决方案1】:

Windows 是一种按需分页的虚拟内存操作系统。使用 operator new 分配内存只会分配 虚拟 内存。在您真正访问内存之前,您不会开始使用物理内存、RAM。你没有这样做。

您可以通过触摸每 4096 个字节来强制分配 RAM,最好进行写入,否则它将被优化掉:

    size_t size = 1024 * 1024;
    ptr[i] = new char[size];
    for (size_t j = 0; j < size; j += 4096) ptr[i][j] = 0;

但这是一件毫无意义的事情,它只会减慢您的程序速度。并且实际上并没有测试任何东西,进程不能在 Windows 上耗尽 RAM。将任务管理器置于程序员模式,添加提交大小列。这是真实的数字。

【讨论】:

  • 请注意,它确实确保在必要时有可用空间。不像某些操作系统,它们撒谎然后不得不开始杀死人以满足内存需求。
  • @Hans Passant:我希望你有技术背景的链接。
  • @DieterLücking:如果不是很多应用程序在做一些事情,比如分配 1MB 来读取文件,并且如果文件小得多,则不会将其重新调整大小。 (同样适用于大型静态分配)。操作系统这样做是因为总体而言,它比执行大型“填充所有页面”更有效且随着时间的推移更分散。只有当所有内存都被许多不同的应用程序高度使用时,它才会真正引起问题 - 这可能意味着您的机器中没有足够的内存。
【解决方案2】:

尝试将数据存储在您的大数组中。 Memset 会做得很好。 如果您不触摸它,您可能正在查看实际内存,这些可能仍然仅在虚拟内存中。

【讨论】:

  • 谢谢戴尔。使用 memset 解决了这个难题。
  • 这是没有意义的事情,它只会减慢程序的速度。
  • @HansPassant:完全没有,它会破坏所有这些页面并创建物理页面。否则这个分配的内存将仅仅指向一个虚拟零页。既然 OP 想要强制系统分配内存,那就对了。
  • @Damon - “强制系统分配内存”到底有什么意义?那测试什么?你认为测试会失败吗?
  • @HansPassant 重点是进行实验并更好地了解操作系统如何管理内存。
【解决方案3】:

也许操作系统过度使用,即。例如,operator new 返回一个有效的(非NULL)指针,尽管内存不足。尝试实际写入一些东西到获得的内存中,你的进程可能会被杀死(或者至少物理内存使用率上升)。

【讨论】:

    【解决方案4】:

    操作系统(无论是 Windows、Linux 还是 MacOS)并不期望所有分配内存的进程都实际使用所有这些内存。许多程序会分配 1MB 来保存文件,然后用 14KB 的文件数据填充它(因为这比弄清楚文件有多大并实际分配正确的数量要容易)。因此,与其费力地让一个真正的物理内存页面可用于可能未使用的内存,它只是将其分配在虚拟空间中,然后在实际使用内存时找到一些物理内存。

    因此,任务管理器中显示的内存量只是您正在使用的实际内存,而不是您已分配但从未使用过的内存。

    如果您编写一个循环写入分配中的每 256 或 1024 个字节,它应该“增长”并显示您实际分配的内存量。

    【讨论】:

      【解决方案5】:

      http://en.wikipedia.org/wiki/Virtual_memory

      您实际上是在用数据填充您的页面文件。操作系统看到您正在分配大量数据,但在您使用它之前,这些数据不会从页面文件中拉到主内存中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-28
        • 2015-09-24
        • 2011-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多