1

我可以将 malloc 放在 do...while 块中以确保成功分配吗?

像:

#define STR_SIZE 1024 * 1024
char *str;
do
    str = (char *) malloc(STR_SIZE);
while ( !str );
4

4 回答 4

8

它可能不会工作,因为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的函数,并在成功时返回分配的区域exitabortmalloc

明智地处理 malloc 失败(即正在做一些事情以能够继续执行)真的很难。一些程序可能例如free一些其他全局数据。实际上这相当于实现了一些专门的垃圾收集机制。一些服务器可能只是使当前请求失败(并且应该非常小心地这样做,释放当前失败请求使用的所有资源)。

malloc当您需要比可用资源更多的资源时,可能会真正失败。所以你必须处理这种情况。

顺便说一句,您可以考虑使用Boehm 的保守垃圾收集器并使用GC_mallocmalloc不是关心它的失败和关于free-ing。(我认为 Boehm 的 GC 会在内存不足时中止程序)。

于 2013-01-06T08:39:49.237 回答
2

正如其他答案所指出的那样,您的代码存在缺陷。然而,背后的想法并非完全不合理。

处理失败的经典方法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 出现故障之前保存他们的工作。

于 2013-01-06T10:16:41.883 回答
1

当然可以,但是如果STR_SIZE不合理,这将永远锁定您的代码。

如果您的内存非常分散,Malloc 也可能会在极少数情况下失败。在这种情况下,您的代码将起作用。

于 2013-01-06T09:18:42.903 回答
-1

你可以,虽然它是一个罕见的 malloc 会失败,语法上正确,但如果它在逻辑上是正确的,我不会,如果它有效,我会尝试编码。

于 2013-01-06T10:48:52.043 回答