Windows如何知道我没有使用内存?

时间:2013-11-03 16:49:31

标签: c++ c windows memory-management malloc

我注意到这种奇怪的效果,其中内存未被Windows任务管理器分配,直到触摸它而不是malloc - ed或new - ed。 debug和优化release版本中都会产生这种效果。

以下是一个结构示例,虽然在我的代码中,分配和利用发生在不同的线程上,所以我不认为它是优化器,虽然我不确定如何检查。

for (int i = 0 ;i < 1000;i++)
{
buffer[i]=malloc(buffersize);
}
_sleep(1000*60)
for (int i=0;i<1000;i++)
{
memset(buffer[i],0,buffersize);//Only shows up the in the resource manager here
}

我的问题是Windows如何知道我使用了内存?它是监视内存以供第一次使用还是一些编译时优化。

我的好奇心是由于我正在写的实时收购,需要我触摸记忆两次 - &gt;一旦分配,一次实际填充数据。因此,按下一个按钮(“aquire!”)需要我一次写入64千兆字节的ram,而不是随着时间的推移,增加了相当多的延迟。如果我{I} malloc这会增加太多延迟。

- 编辑 -

我还禁用了Windows页面文件......

4 个答案:

答案 0 :(得分:7)

这是Windows等需求页面虚拟内存操作系统的标准行为。 malloc()调用仅分配虚拟内存地址空间。在访问内存之前,您实际上并未开始使用RAM。这会产生页面错误,迫使操作系统将您访问的内存页映射到RAM中。

这通常是软页面错误,通过从空闲列表中抓取RAM页面并映射它来非常快速地处理。与硬页面错误相反,当一些RAM页面再次换出到交换文件时,你会受到影响,因为另一个进程需要RAM。从磁盘重新加载页面需要更多时间。

禁用分页文件有助于避免这些硬页面错误。它并没有消除它们,你的代码页也会被换掉。当您强制操作系统退回到它们时,可能会发生这种情况,因为它无法再切换到页面文件。这样的页面在换出时就被丢弃了,当页面出现故障时从可执行文件重新加载。

如果您有软实时要求,那么最好的策略是尽早分配内存并在您开始承诺快速响应之前有意访问它。可以简单地用calloc()而不是malloc()完成。

答案 1 :(得分:3)

分配给您的进程的虚拟地址空间不一定由物理RAM支持。一个示例是页面文件,其中如果物理RAM运行不足,则可以将正在使用的内存移动到该文件。但是,如果你从未写过它,就不必分配任何物理RAM或磁盘空间。因此,作为优化,某些操作系统会为您提供虚拟地址空间,而无需为其实际分配空间。在某些情况下,这是非常有益的。在其他情况下,和你的一样,这有点烦人。

也就是说,任务管理器是一个非常简单的工具,用于调查内存使用情况。你能够观察到这一点更加幸运,只使用任务管理器就无法(可靠地)观察到许多问题。

至于如何在不触及所有内存的情况下避免延迟分配......我不知道有什么办法。甚至VirtualAlloc都没有解决这个问题。 您可以通过每页只写一个字节来降低成本,这仍然会导致物理RAM分配。但请记住,即使您可以避免编写任何,Windows仍然需要分配1600万页,包括页表条目。这肯定需要一些时间。您可以使用大页面(使用VirtualAlloc),这会使页面大几百倍,从而将上述1600万页减少到更合理的数字。

答案 2 :(得分:1)

好像您的操作系统懒惰地分配内存。查看this question

的答案

基本上,当您调用malloc时,操作系统会为您的程序提供一个地址,并承诺以所请求的数量提供内存。我读过的类比是操作系统“为内存写了一张支票”,但只在程序试图通过使用它来“兑现”支票时才分配物理内存。

我认为,如果您希望在malloc时出现延迟命中,那么您应该memset

答案 3 :(得分:1)

您可以同时尝试malloc并立即为其分配一个空值,以克服NicholasM所说的'懒惰内存分配'。即使这样,编译器也可能会发现您正在分配但不使用分配,并将它们从已编译的代码中删除。但是不要忘记为什么操作系统懒惰地分配内存。