从来没有发生在我身上,而且我已经编程多年了。
有人能举例说明malloc
实际上不起作用的非平凡程序吗?
我不是在谈论内存耗尽:我正在寻找一个简单的情况,当你只分配一个由用户给出的绑定大小的内存块时,假设一个整数,导致malloc
失败。
答案 0 :(得分:22)
你需要在嵌入式系统中做一些工作,你经常会在那里返回NULL: - )
在现代大容量地址空间和后备存储系统中耗尽内存要困难得多,但在处理大量数据的应用程序中,例如GIS或内存数据库,或在您的错误代码导致内存泄漏的地方。
但是,你以前从未体验过它并不重要 - 标准说它可能会发生,所以你应该迎合它。在过去的几十年里,我也没有被汽车击中,但这并不意味着我没有先看过去就在公路上徘徊。
重新编辑:
我不是在谈论内存耗尽,......
内存耗尽的定义是malloc
没有给你所需的空间。无论是分配所有可用内存还是堆碎片导致无法获得连续块,即使内存区域中所有空闲块的聚合更高,或者使用符合标准的功能人为限制地址空间使用也无关紧要:
void *malloc (size_t sz) { return NULL; }
C标准不区分失败的模式,只是成功或失败。
答案 1 :(得分:16)
是
尝试malloc
比系统提供的内存更多(通过耗尽地址空间或虚拟内存 - 以较小者为准)。
malloc(SIZE_MAX)
可能会这样做。如果没有,重复几次直到你用完为止。
答案 2 :(得分:8)
任何用c编写的程序都需要动态分配比OS当前允许的内存更多的内存。
为了好玩,如果你在
中使用ubuntu类型 ulimit -v 5000
您运行的任何程序很可能会崩溃(由于malloc失败),因为您已将任何一个进程的可用内存量限制为精简数量。
答案 3 :(得分:7)
除非您的内存已经完全保留(或严重分段),否则让malloc()
返回NULL
指针的唯一方法是请求大小为零的空间:
char *foo = malloc(0);
引用C99标准,§7.20.3,第1小节:
如果请求的空间大小为零,则行为是实现定义:返回空指针,或者行为就好像大小是某些 非零值,但返回的指针不得用于访问对象。
换句话说,malloc(0)
可能会返回一个NULL
指针或一个指向零分配字节的有效指针。
答案 4 :(得分:4)
只需查看malloc
的手册页。
成功时,指向由函数分配的内存块的指针 此指针的类型始终为void *,可以将其强制转换为所需类型的数据指针,以便可以取消引用。
如果函数未能分配所请求的内存块,则返回空指针。
答案 5 :(得分:3)
选择任何平台,虽然嵌入式可能更容易。 malloc
(或new
)一吨RAM(或随着时间的推移泄漏RAM,甚至使用朴素算法将其分段)。繁荣。当{"糟糕"}时,malloc
确实会为我回复NULL
事情正在发生。
回复您的编辑。是的,再次。随着时间的推移,内存碎片可能会使int
的单个分配失败。另请注意,malloc
不会为int
分配4个字节,但可以获取所需的空间。它有自己的簿记功能,通常最少可以占用32-64字节。
答案 6 :(得分:3)
既然你问过一个例子,这里有一个程序(最终)会看到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。
答案 7 :(得分:3)
在一个或多或少的标准系统上,使用标准的单参数malloc,有三种可能的失败模式(我能想到):
1)不允许分配请求的大小。例如,某些系统可能不允许分配> 16M,即使有更多存储空间。
2)所请求大小的连续空闲区域(默认边界)不能位于堆中。可能仍然有很多堆,但只是一块不够。
3)总分配堆超过了一些“人为”限制。例如,用户可能被禁止分配超过100M,即使有200M空闲且可用于单个组合堆中的“系统”。
(当然,你可以获得2和3的组合,因为有些系统会在增长时为堆分配非连续的地址空间块,将“堆大小限制”放在块的总数上。)< / p>
请注意,某些环境支持额外的malloc参数,例如对齐和池ID,这些参数可以添加自己的扭曲。
答案 8 :(得分:1)
是。当内核/系统lib确定无法分配内存时,Malloc将返回NULL。
您通常在现代机器上看不到这一点的原因是,Malloc并不真正分配内存,而是请求为您的程序保留一些“虚拟地址空间”,以便您可以在其中写入。像现代Linux这样的内核实际上过度提交,就是它们允许你分配比你的系统实际提供的内存更多的内存(swap + RAM),只要它们都适合系统的地址空间(通常是64位平台上的48位,IIRC) 。因此,在这些系统上,您可能会在触发返回NULL指针之前触发OOM杀手。一个很好的例子是32位机器中的512MB RAM:编写一个可被OOM杀手吃掉的C程序是微不足道的,因为它试图将所有可用的RAM +交换为malloc。
(在Linux上编译时可以禁用过度命令,因此它取决于构建选项,无论给定的Linux内核是否会过度使用。但是,库存桌面发行版内核会这样做。)
答案 9 :(得分:0)
当 malloc 参数为负数或 0 或堆上没有剩余内存时。 我不得不更正某人的代码,看起来像这样。
const int8_t bufferSize = 128;
void *buffer = malloc(bufferSize);
这里的buffer是NULL,因为bufferSize实际上是-128