这里用一个C程序来介绍这个问题。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
if(argc != 2) {
printf("Provide a number to indicate the number of bytes (in Mega)\n");
exit(8);
}
int num = atoi(argv[1]);
size_t max = num * pow(2, 18);
printf("declared %ld ints\n", max);
int *a = malloc(max * sizeof(int));
while(1) {
for(size_t i = 0; i < max; i++) {
a[i];
}
}
return 0;
}
该程序做简单的事情。它从输入中读取一个数字,例如 n,然后通过 malloc 请求 n MB 内存。
问题是当我启动程序并在终端(Linux中)中输入free时,结果发现free指示的已用内存比请求的内存小得多(如果你给出一个大的n)。
这是我输入
./a.out 1000
后 free 的输出
$ free -h
total used free shared buff/cache available
Mem: 12Gi 649Mi 11Gi 0.0Ki 320Mi 11Gi
Swap: 4.0Gi 0B 4.0Gi
pmap 的更详细输出
$ pmap 18414 -x
18414: ./a.out 1000
Address Kbytes RSS Dirty Mode Mapping
00005642164b8000 4 4 0 r---- a.out
00005642164b9000 4 4 0 r-x-- a.out
00005642164ba000 4 4 0 r---- a.out
00005642164bb000 4 4 4 r---- a.out
00005642164bc000 4 4 4 rw--- a.out
0000564218248000 132 4 4 rw--- [ anon ]
00007fa6d1b9a000 1024016 12 12 rw--- [ anon ]
00007fa71039e000 160 160 0 r---- libc.so.6
00007fa7103c6000 1620 852 0 r-x-- libc.so.6
00007fa71055b000 352 148 0 r---- libc.so.6
00007fa7105b3000 16 16 16 r---- libc.so.6
00007fa7105b7000 8 8 8 rw--- libc.so.6
00007fa7105b9000 52 20 20 rw--- [ anon ]
00007fa7105d0000 8 4 4 rw--- [ anon ]
00007fa7105d2000 8 8 0 r---- ld-linux-x86-64.so.2
00007fa7105d4000 168 168 0 r-x-- ld-linux-x86-64.so.2
00007fa7105fe000 44 44 0 r---- ld-linux-x86-64.so.2
00007fa71060a000 8 8 8 r---- ld-linux-x86-64.so.2
00007fa71060c000 8 8 8 rw--- ld-linux-x86-64.so.2
00007ffdc8b06000 136 12 12 rw--- [ stack ]
00007ffdc8b9b000 16 0 0 r---- [ anon ]
00007ffdc8b9f000 4 4 0 r-x-- [ anon ]
---------------- ------- ------- -------
total kB 1026776 1496 100
当我将for循环中的句子修改为
a[i] = 1;
时,事情变得有趣了。当我写入内存时,free和pmap告诉我物理内存实际上使用了1000MB。
为什么会发生这种情况?读取堆不会将新页面带到物理内存,但是“写入”呢?我怀疑这与所谓的匿名文件有关。然而,对此的讨论却很少。我没能在网上找到有用的东西。
如果有人可以提供帮助,我将非常感激。
函数malloc()会分配一块内存,接收到的内存块的内容并没有初始化。这意味着它只是内存管理中的一条记录。
当你只是“读”它时,我认为编译器会把它优化得一无是处。您可以通过检查汇编代码来确认。