现代64位系统上,什么原因会导致内存分配失败?

4
假设进程中有足够的虚拟内存地址。
考虑到 64 位系统几乎具有无限的虚拟地址,如果操作系统内存池中仍有可用的物理内存空间,我们可以假设内存分配不会失败吗?

4
您可能想了解内存碎片化。即使虚拟地址空间非常大,可用的内存仍然受限于物理RAM和交换空间的总量,这可能比您想象的要少。 - Some programmer dude
3
不同的操作系统对于应用程序可使用的内存量有不同的限制,这些限制可以由系统进行设置。如果一个应用程序只编译为32位架构,那么可能会出现应用程序或库失败的情况。内存碎片化和四舍五入可能会导致内存浪费,但通常不会在正常使用情况下导致内存分配失败(例如malloc N直到内存几乎满了,释放每个第二个块,malloc 2N可能会失败,但实际上已经使用了整体内存的相当大一部分)。 - Tony Delroy
1
“几乎无限的虚拟地址”?人们曾经这样说过1MB系统。 :-) - chux - Reinstate Monica
1个回答

6
这要看情况。你可以通过限制进程使用资源(例如在Linux上使用setrlimit(2)),有很多好处,比如避免错误程序占用所有资源,留出一些资源给其他更重要的进程。
因此,一个表现良好的程序应该始终测试内存分配(例如malloc(3)operator new,它们通常基于较低级别的系统调用,如mmap(2)...)。当然,资源并不是无限的(最多是物理RAM + 交换空间)。
通常,在内存耗尽时,唯一需要做的就是用友好的消息中止程序(能够被系统管理员理解)。做更复杂的事情要困难得多,但是可能是必需的(在服务器程序中是必须的,因为您希望继续服务其他请求...)。
因此,你应该用C语言编写:
 void* p = malloc(somesize);
 if (!p) { perror("malloc"); exit(EXIT_FAILURE); };

你可以使用_exitabort,如果你担心通过atexit(3)注册的终止器会执行malloc...但我不会管它。
通常,执行上述操作的例程因历史原因被称为xmalloc
在C++中,operator new可能会通过抛出一个std::bad_alloc异常(或者如果你使用new(std::nothrow),则会给出nullptr,详见std::nothrow)。

了解有关Linux上内存超额配置虚拟内存以及如Joachim Pileborg所评论的内存碎片化的更多信息。阅读垃圾回收的相关内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接