【问题标题】:malloc in do while blockmalloc 在 do while 块中
【发布时间】:2012-12-20 06:35:51
【问题描述】:

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

喜欢:

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

【问题讨论】:

  • 最好解释一下你正在编写什么样的应用程序。
  • @BasileStarynkevitch ,typedef struct _LIST LIST, *PLIST; struct _LIST { PLIST pre; PLIST next; }; /* Create a new node */ PLIST node; do node = (PLIST) malloc(sizeof(LIST)); while (!node);
  • 请编辑您的问题。但这并不能描述您正在编码的应用程序是什么种类?它是一个服务器应用程序,应该尽可能长时间地运行(即使资源有限),还是一个命令行应用程序?它是一些对生命至关重要的嵌入式应用程序(例如起搏器软件)吗?为什么你绝对希望malloc 成功?你知道malloc的故障模式吗??
  • @BasileStarynkevitch , 这是一个命令行工具。
  • 然后,您只需要在malloc 失败时以perror 退出。在这种情况下无需确保成功分配。

标签: c malloc


【解决方案1】:

它可能不会工作,因为malloc很少失败,当资源耗尽时它会失败,并且这些不会很快可用。

malloc 可以获得更多资源的唯一常见情况是,如果某个其他大进程释放了大量内存,这种情况很少发生,也可能永远不会发生;如果您关心这一点,请在循环中至少添加一个sleep,并准备好在malloc 真正失败并始终返回NULL 时处理这种情况。

更好的做法是测试malloc 结果并退出并显示失败和错误消息,例如

  char* str = malloc(STR_SIZE);
  if (!str) {
      perror("malloc failed for str");
      exit (EXIT_FAILURE);
  }

每个程序都应该处理malloc 失败的情况(通常是通过退出并显示错误消息)。

很多程序调用xmalloc一个函数,当malloc失败时exit-s或abort-s,成功时返回分配的区域

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

当您需要比可用资源更多的资源时,malloc 可能真的会失败。所以你必须处理那个案子。

顺便说一句,您可以考虑使用Boehm's conservative garbage collector 并使用GC_malloc 而不是malloc,而不关心它的失败和free-ing。 (我认为 Boehm 的 GC 会在内存不足时中止程序)。

【讨论】:

    【解决方案2】:

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

    处理malloc 失败的经典方法是让程序退出,如Basile's answer 中所述。检查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 网络服务器。

    在交互式应用程序中malloc 失败的另一种方法是 Emacs 使用的方法:在启动时分配固定数量的内存并保存以供以后使用。当内存分配失败时,释放内存并引发 Lisp 级异常,放弃当前操作。向用户显示一条警告消息,解释情况。释放的内存使程序能够继续工作足够长的时间,以便用户在 Emacs 宕机之前保存他们的工作。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-01
          • 2020-05-07
          • 2016-02-21
          • 2013-04-10
          • 2016-07-30
          • 2020-08-21
          相关资源
          最近更新 更多