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

时间:2015-07-23 12:08:48

标签: c linux linux-kernel operating-system

我正在读书:

  

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

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

3 个答案:

答案 0 :(得分:9)

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

对于可用于分配内存的所有其他函数也是如此。最终它们最终都是brk()mmap系统调用。 mmap()的长度参数也是ssize_t类型,如果是brk(),则必须为分配的空间的新结尾提供指针。指针再次是32位。

所以绝对没有办法告诉内核你希望通过一次通话分配超过4GB的内存)并且这不是偶然的 - 这无论如何都没有任何意义。< / p>

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

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

int main() {
    assert(malloc(5*1<<30));
}

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

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

答案 1 :(得分:2)

已经有了一个很好的答案。以防万一,虚拟地址空间的大小很容易验证,如下所示:

#include <stdlib.h>
#include <stdio.h>

int main()
{
    size_t size = (size_t)-1L;
    void *foo;

    printf("trying to allocate %zu bytes\n", size);

    if (!(foo = malloc(size)))
    {
        perror("malloc()");
    }
    else
    {
        free(foo);
    }
}
  

&GT; gcc -m32 -omalloc malloc.c&amp;&amp; ./malloc
  试图分配4294967295字节
  malloc():无法分配内存

这必定会失败,因为地址空间的某些部分已被占用:当然,由内核的映射部分,映射的共享库和程序占用。

答案 2 :(得分:1)

您无法执行此操作,因为您无法分配5GB内存。