我可以将 malloc 放在 do...while 块中以确保成功分配吗?
像:
#define STR_SIZE 1024 * 1024
char *str;
do
str = (char *) malloc(STR_SIZE);
while ( !str );
它可能不会工作,因为malloc
很少失败,当资源耗尽时它会失败,而且这些不会很快可用。
获得更多资源的唯一常见情况malloc
是,如果某个其他大进程释放了大量内存,这种情况很少发生,也可能永远不会发生;如果您关心它,sleep
请在循环中至少添加 a ,并准备好在malloc
真正失败并始终返回时处理这种情况NULL
。
更好的做法是测试malloc
结果并退出失败和错误消息,例如
char* str = malloc(STR_SIZE);
if (!str) {
perror("malloc failed for str");
exit (EXIT_FAILURE);
}
并且每个程序都应该处理malloc
失败的情况(通常是通过退出并显示错误消息)。
很多程序在失败时调用-s或-sxmalloc
的函数,并在成功时返回分配的区域exit
abort
malloc
明智地处理 malloc 失败(即正在做一些事情以能够继续执行)真的很难。一些程序可能例如free
一些其他全局数据。实际上这相当于实现了一些专门的垃圾收集机制。一些服务器可能只是使当前请求失败(并且应该非常小心地这样做,释放当前失败请求使用的所有资源)。
malloc
当您需要比可用资源更多的资源时,可能会真正失败。所以你必须处理这种情况。
顺便说一句,您可以考虑使用Boehm 的保守垃圾收集器并使用GC_malloc
而malloc
不是关心它的失败和关于free
-ing。(我认为 Boehm 的 GC 会在内存不足时中止程序)。
正如其他答案所指出的那样,您的代码存在缺陷。然而,背后的想法并非完全不合理。
处理失败的经典方法malloc
是退出程序,如Basile 的回答中所述。检查. malloc
_ xmalloc
_ malloc
这很容易实现和推理,但并非没有缺陷。这对于短命的命令行程序很有意义,例如那些通常从 Unix shell 调用的命令行程序,但是对于不适合让程序立即死机的交互式程序,即使它确实耗尽了内存,它也会失败. 它也不适合库代码,因为使用库的程序可能不希望进程仅仅因为单个分配失败而退出。
当内存问题很可能不是由程序的活动引起时,重试分配是有意义的。例如,多进程 HTTP 服务器可能不想在单个内存分配失败时拒绝请求并立即结束进程。但是,一个好的实现应该:1)注意在请求之间休眠以避免忙循环并给系统一个恢复的机会,以及 2)确保进程在多次迭代后退出,以防它是进程本身导致分配失败。例如:
void *safe_malloc(size_t howmuch)
{
int i = 0;
while (i++ < 10) {
void *ptr = malloc(howmuch);
if (ptr)
return ptr;
sleep(i);
}
perror("malloc");
exit(EXIT_FAILURE);
}
这种方法已用于服务器,例如现已过时的phttpd Web 服务器。
Emacs 使用了另一种解决交互式应用程序失败的方法malloc
:在启动时分配固定数量的内存并保存以备后用。当内存分配失败时,释放内存并引发 Lisp 级异常,放弃当前操作。向用户显示一条警告消息,解释情况。释放的内存使程序能够继续工作足够长的时间,以便用户在 Emacs 出现故障之前保存他们的工作。
当然可以,但是如果STR_SIZE
不合理,这将永远锁定您的代码。
如果您的内存非常分散,Malloc 也可能会在极少数情况下失败。在这种情况下,您的代码将起作用。
你可以,虽然它是一个罕见的 malloc 会失败,语法上正确,但如果它在逻辑上是正确的,我不会,如果它有效,我会尝试编码。