这种情况从未发生在我身上,因为我已经编程多年了。
有人能给我举一个非平凡的程序例子吗,在这个程序中malloc
实际上不起作用?
我不是在谈论内存耗尽的情况: 我正在寻找一个简单的情况,当您分配一个由用户给定的边界大小的单个内存块(比如一个整数)时,malloc
会失败。
这种情况从未发生在我身上,因为我已经编程多年了。
有人能给我举一个非平凡的程序例子吗,在这个程序中malloc
实际上不起作用?
我不是在谈论内存耗尽的情况: 我正在寻找一个简单的情况,当您分配一个由用户给定的边界大小的单个内存块(比如一个整数)时,malloc
会失败。
void *malloc (size_t sz) { return NULL; }
malloc
无法提供您所需的内存。无论您是否完全没有内存或者您请求了60个字节,而分配器有10亿个30字节的块无法合并,都没有关系。在这两种情况下,都属于内存耗尽。无论如何,一个每十次调用就返回NULL的malloc
(由真正的虐待狂编写)仍然符合标准。 - paxdiablo可以。
只需尝试使用malloc
申请比系统可提供的内存更多的内存(通过耗尽地址空间或虚拟内存中较小的内存,两者之一)即可。
malloc(SIZE_MAX)
可能会这样做。如果不行,重复几次直到用尽为止。
malloc()
经常会返回NULL
。 - Ferruccio ulimit -v 5000
你运行的任何程序都很可能会崩溃(由于malloc失败),因为你将任何一个进程可用内存的限制降到了一个微不足道的程度。
除非内存已被完全保留(或严重碎片化),否则malloc()
只有请求大小为零的空间时才会返回一个NULL
指针:
char *foo = malloc(0);
根据C99标准第7.20.3节的第1小节规定:
如果请求的内存大小为零,则行为是实现定义的:要么返回空指针,要么行为就像请求了一些非零大小的空间一样,但返回的指针不能用于访问对象。
换句话说,malloc(0)
可能会返回一个NULL
指针或一个指向零字节分配的有效指针。
malloc
(或new
)分配大量内存(或随着时间的推移泄漏内存,甚至通过使用天真的算法使内存碎片化)。完成了。malloc
在发生“坏”操作时偶尔会返回NULL
。int
分配失败。还要记住,malloc
不仅为int
分配4个字节,而且可以获取尽可能多的空间。它有自己的记账工具,通常会最少占用32-64个字节。malloc
也可能会失败。(我也喜欢关于虚拟内存和过度承诺的补充回答。) - user166390只需查看malloc
的手册页。
成功时,函数返回指向所分配内存块的指针。
这个指针的类型总是void*,可以强制转换为所需的数据指针类型以便进行引用。
如果函数未能分配所请求的内存块,则返回空指针。
是的。当内核/系统库确定无法分配内存时,Malloc将返回NULL。
通常在现代计算机上看不到这种情况的原因是Malloc并不真正分配内存,而是请求为程序保留一些“虚拟地址空间”,以便您可以在其中写入数据。像现代Linux这样的内核实际上会过度承诺,也就是说,只要所有内存都适配于系统的地址空间(通常是64位平台上的48位),它们就可以让您分配比系统实际可提供的更多的内存(交换+RAM)。因此,在这些系统上,您可能会在触发返回NULL指针之前触发OOM killer。例如,在32位机器上具有512MB RAM的情况下,很容易编写C程序,该程序由于尝试malloc所有可用的RAM +交换而被OOM killer吃掉。
(在Linux上可以在编译时禁用Overcomitting,因此这取决于构建选项是否给定的Linux内核会过度承诺。但是,桌面发行版内核默认启用它。)
既然您要求提供示例,这里有一个程序,最终会看到 malloc
返回 NULL
:
perror();void*malloc();main(){for(;;)if(!malloc(999)){perror(0);return 0;}}
什么?你不喜欢故意混淆的代码吗?;)(如果它在你的机器上运行几分钟而不崩溃,请杀掉它,将999
更改为更大的数字,然后再尝试。)
编辑:如果无论数字有多大都无法正常工作,则说明您的系统正在说“这里有一些内存!”但只要您不尝试使用它,它就不会被分配。在这种情况下:
perror();char*p;void*malloc();main(){for(;;){p=malloc(999);if(p)*p=0;else{perror(0);return 0;}}
这应该能解决问题。如果我们可以使用GCC扩展,通过将char*p;void*malloc();
更改为void*p,*malloc();
,我们甚至可以让它更小,但如果您真的想要高尔夫球,您可能会去Code Golf SE。
malloc
从不返回 NULL
。相反,在分配了大约50 GiB的虚拟内存后,程序会收到 SIGKILL
信号。 - tbodt当malloc参数为负数或0,或者堆上没有剩余内存时,会出现问题。我不得不纠正某人的代码,它看起来像这样。
const int8_t bufferSize = 128;
void *buffer = malloc(bufferSize);
这里buffer是NULL的原因是因为bufferSize实际上是-128
malloc()
返回了NULL
。另一方面,它_可能_已经起作用了。当“malloc参数为...0”时是另一回事。 - chux - Reinstate Monica
malloc
无法成功,它将失败。它能否成功取决于您的系统和堆的当前状态。如果您在主函数中分配一个1字节的块并立即返回,则不太可能失败。如果您有一个真正的程序需要完成一些实际工作,那么在某些情况下可能会失败。这样说是否够清楚明了? - Useless