c - 为什么我们可以分配一个 1 PB (10^15) 的数组并访问最后一个元素,但不能释放它?

标签 c linux malloc mmap virtual-address-space

众所周知:http://linux.die.net/man/3/malloc

By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. In case it turns out that the system is out of memory, one or more processes will be killed by the OOM killer.

并且我们可以使用malloc(petabyte);成功分配1 PB的VMA(虚拟内存区域):http://ideone.com/1yskmB

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

int main(void) {

    long long int petabyte = 1024LL * 1024LL * 1024LL * 1024LL * 1024LL;    // 2^50
    printf("petabyte %lld \n", petabyte);

    volatile char *ptr = (volatile char *)malloc(petabyte);
    printf("malloc() - success, ptr = %p \n", ptr);

    ptr[petabyte - 1LL] = 10;
    printf("ptr[petabyte - 1] = 10; - success \n");

    printf("ptr[petabyte - 1] = %d \n", (int)(ptr[petabyte - 1LL]));

    free((void*)ptr);   // why the error is here?
    //printf("free() - success \n");

    return 0;
}

结果:

Error   time: 0 memory: 2292 signal:6
petabyte 1125899906842624 
malloc() - success, ptr = 0x823e008 
ptr[petabyte - 1] = 10; - success 
ptr[petabyte - 1] = 10 

并且我们可以成功访问(存储/加载)到 PB 的最后一个成员,但是为什么我们在 free((void*)ptr); 上出错?

注:https://en.wikipedia.org/wiki/Petabyte

  • 1000^5 PB PB
  • 1024^5 PiB pebibyte - 我用它

所以实际上,如果我们想要分配超过 RAM + 交换空间的内存并解决 overcommit_memory 限制,那么我们可以通过在 Windows 上使用 VirtualAllocEx() 或在 Linux 上使用 mmap() 来分配内存,例如:

最佳答案

我认为您的问题是 malloc() 没有将 long long int 作为其参数。它需要一个 size_t

更改代码将 petabyte 定义为 size_t 后,您的程序不再从 malloc 返回指针。相反,它失败了。

我认为您的数组访问权限将 PB-1 设置为 10 的写入远远超出了 malloc 返回的数组。那就是崩溃。

调用函数时始终使用正确的数据类型。

使用这段代码看看发生了什么:

long long int petabyte = 1024LL * 1024LL * 1024LL * 1024LL * 1024LL;
size_t ptest = petabyte;
printf("petabyte %lld %lu\n", petabyte, ptest);

如果我在 64 位模式下编译,它无法 malloc 1 PB。如果我在 32 位模式下编译它 mallocs 0 字节,成功,然后尝试在它的数组之外写入和段错误。

关于c - 为什么我们可以分配一个 1 PB (10^15) 的数组并访问最后一个元素,但不能释放它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38568247/

相关文章:

c - 带有两个变量的 switch case

检查linux中特定程序使用的服务

linux - 能够连接到对象服务器,但不能打开 Realm

c - 读取输入并将其放入字符指针

c - return 在返回结构时从指针生成整数而不进行强制转换

c - 将对象数组传递给 Objective C 中的函数——并返回一个对象

c - 在 C 中比较字符串时,fgets 比 scanf 更有效吗?

c - ASM 到 C : What does 4(%esp) refer to

linux - 如何更改ld.so中的默认路径

c - 函数调用内的 Malloc 似乎在返回时被释放?