我在 64 位系统中运行附加代码,因此我期望对于这个缓冲区字节(21B),我能够分配内存,但 calloc 无法做到这一点,因此它返回一个 NULL 指针。对于较小的缓冲区字节(如 20 B),它会很好,但在 21 B 时会中断,并且当我检查不同的机器时,这个断点可能会有所不同。我只需要知道我应该在该系统中检查什么,它会阻止我进行内存分配?
#include <unistd.h>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
int main(int argc, char* const argv[])
{
size_t bufferBytes = 21000000000;
// size_t bufferBytes = 20000000000;
// Use words instead of bytes to ensure 8-byte alignment.
size_t bufferWords = bufferBytes / 8;
auto m_buffer = reinterpret_cast<char *>(calloc(bufferWords, 8));
if(m_buffer==NULL)
{
std::cout<<"Not a valid pointer"<<std::endl;
}
}
“我可以使用
malloc
分配多少内存”这一经典问题取决于多种因素,例如您的操作系统、malloc
/calloc
的库实现以及您拥有多少 RAM。
但是,一般来说,对于如此巨大的分配,库实现完全绕过堆并直接进入操作系统服务(Linux 上为
mmap
,Windows 上为 VirtualAlloc
)。由操作系统决定对这些分配施加什么限制。例如,我的机器单个 calloc
的最高容量为 52GB(具有 16GB 物理 RAM)。
64 位系统的虚拟地址空间(目前)非常大。然而,对于物理地址空间来说情况并非如此,大多数消费者计算机都具有 8-32GB RAM。
当您需要如此大的分配时,您的操作系统实际上并没有为您保留任何物理内存,而只是将虚拟地址空间中的某个区域标记为可用。当您实际尝试访问该内存时,操作系统实际上会为您分配它。您可以通过在任务管理器(或 Linux 上的
htop
)中检查进程来查看这一点。在程序的最后添加一个while(1);
,你会发现你的程序几乎不使用任何内存。
一旦您开始使用比实际 RAM 多的内存,操作系统就会开始将其交换到磁盘(使您的计算机运行速度非常慢),以便在 RAM 中腾出空间。然而,它只能在一定程度上做到这一点。它无法使用硬盘驱动器上的数百 GB 空间进行交换。因此,操作系统将达到一定的大小(请参阅 Linux 上的setrlimit),这样它就不会向您保证它可能无法提供的内存。