我正在读书:
32位机器上的进程的虚拟地址空间是2 ^ 32,即4Gb的空间。并且程序中看到的每个地址都是虚拟地址。 4GB的空间进一步通过用户/内核拆分3-1GB。
为了更好地理解这一点,我做了5Gb空间的malloc()并尝试打印所有地址。如果我打印地址,当应用程序只有3GB的虚拟地址空间时,应用程序如何打印整个5Gb地址?我在这里错过了什么吗?
答案 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内存。