malloc()32位机器上的5GB内存

Shi*_*hra 0 c linux operating-system linux-kernel

我正在读一本书:

32位机器上进程的虚拟地址空间为2 ^ 32,即4Gb空间.并且程序中看到的每个地址都是虚拟地址.4GB的空间进一步通过用户/内核拆分3-1GB.

为了更好地理解这一点,我做了5Gb空间的malloc()并尝试打印所有地址.如果我打印地址,当应用程序只有3GB的虚拟地址空间时,应用程序如何打印整个5Gb地址?我在这里错过了什么吗?

Krz*_*ski 9

malloc()size_t作为参数.在32位系统上,它是某些无符号32位整数类型的别名.这意味着您无法传递任何大于2^32-1参数的值,因为malloc()使用此函数无法请求分配超过4GB的内存.

对于可用于分配内存的所有其他函数也是如此.最终他们最终都成为了一个brk()mmap系统调用.长度参数mmap()也是类型ssize_t的情况下的brk(),你必须为你的分配空间的新的终端的指针.指针再次是32位.

所以绝对没有办法告诉内核你想通过一次调用分配超过4GB的内存)并且这不是偶然的 - 这无论如何都没有任何意义.

现在你可以对malloc或其他分配内存的函数进行多次调用,总共请求超过4GB.如果您尝试这样做,后续调用(这将导致扩展分配的内存超过3GB)将失败,因为没有可用的地址空间.

所以我猜你要么没有检查malloc返回值,要么你尝试运行这样的代码(或类似的东西):

int main() {
    assert(malloc(5*1<<30));
}
Run Code Online (Sandbox Code Playgroud)

并假设您成功分配了5GB但没有验证您的参数溢出而不是请求5368709120字节,而是请求1073741824.在Linux上验证这一点的一个示例是使用:

$ ltrace ./a.out __libc_start_main(0x804844c, 1, 0xbfbcea74, 0x80484a0, 0x8048490 <unfinished ...> malloc(1073741824) = 0x77746008 $