【问题标题】:Is there any reason to not turn null check after malloc into a function?有什么理由不把 malloc 后的空检查变成一个函数吗?
【发布时间】:2015-04-07 20:50:56
【问题描述】:

C 中,当我们使用malloc 系列函数时,我们应该添加一个条件来检查分配是否成功,如果不成功,则打印一条消息。

如果我的代码中有很多分配,我有什么理由不应该把它变成一个函数吗?即:

void nullcheck(void * x){
    if (x == NULL){
        printf("Memory allocation has failed");
        exit(1);
    }
}

并调用函数:

int * a = malloc(sizeof(int));
nullcheck(a);

它使代码更好更短,有什么理由不应该这样做吗?

【问题讨论】:

  • 你会在之前调用malloc时泄露内存。
  • 有时,由于内存分配失败而调用exit 并不是一个理想的策略。例如,一个应用程序可能更喜欢记录错误,并能够继续做其他事情。
  • @mch:如果您完全退出程序,那么这不太可能。
  • 通常你想在退出程序之前做一些清理工作(关闭打开的文件、套接字......)。函数内部的热门exit(1) 会阻止您这样做。
  • ...您可以使用atexit 注册这些东西

标签: c syntax malloc


【解决方案1】:

有什么理由不应该这样做吗?

如果您的应用程序有能力在分配失败后立即退出,那么请务必将其设为一个函数,并将其合并到分配函数中。

如果您编写的代码需要表现得更好(例如库),则不能这样做,因为通常必须在释放成功分配的任何内容后返回错误代码。

在后一种情况下,模式如下所示:

p1 = malloc(…);
if (!p1) goto error;
p2 = malloc(…);
if (!p2) goto free1;
p3 = malloc(…);
if (!p3) goto free2;
…
free2:
free(p2);
free1:
free(p1);
error:
return -1;

【讨论】:

  • 我通常会看到每个条件都跳转到同一个标签,因此清理代码将始终执行free(p2); free(p1); return -1,因为释放空指针是无操作的。
  • @Kos 这是另一种可能性,但它不能推广到其他类型的资源。例如,fclose(NULL); 没有记录为无操作。
【解决方案2】:

为什么不在一个函数中做所有事情?

void *unrecoverable_malloc(size_t size)
{
    void *x = malloc(size);

    if (x) {
        return x;
    }

    fprintf(stderr, "Memory allocation has failed.\n");
    exit(1);
}

虽然x = malloc(); if (!x) { /* recover */ } 模式很常见(也是很好的做法),但从 OOM 状态中恢复非常困难。它给你一种检查分配失败的温暖和模糊的感觉,但在一个足够复杂的应用程序中,无论你做什么来恢复都可能无论如何都行不通。

【讨论】:

  • 这假定fprintf 不会在内部分配任何内存,但无论如何。
  • 非常好,为什么fprintf而不是printf
  • 关于“无论你做什么来恢复可能都不管用”,你的意思是说像你的答案那样做它并不重要,因为 OOM 很难恢复?
  • @SeanBright:取决于您编写的代码类型。如果您的代码会影响真人的安全,不,您不能忽略 OOM 情况的可能性。并不意味着你可以做很多事情,但你至少知道,你可以停止执行。也取决于平台。
  • @EdS。很公平。但是,当您的应用程序的核心要求之一是“保护人类生命”时,关于安全降级的讨论远远超出了“如果单次分配失败,我们如何恢复”这样的琐碎问题。如果你为 NASA 或 Lockheed 工作并且正在阅读这篇文章,请忽略我所说的一切! :-)
【解决方案3】:

那(几乎)没问题;只要您每次都以完全相同的方式处理错误。然而;在我看来,一个名为nullcheck 的函数不返回任何内容,并且可能退出该程序充其量只是命名不当。

【讨论】:

  • 同意。在这种情况下,您最好使用assert
【解决方案4】:

Q:有什么理由不把malloc之后的null检查变成一个函数吗?
A:是的:极端情况:分配 0

malloc()calloc() 等返回NULL 本身并不一定表示内存不足。

当请求的数量为0 时,分配函数可能会返回NULL。或者,这些函数可能会返回一个非NULL 指针。

考虑将malloc() 和测试放入 1 个函数中。

void *malloc_check(size_t n) {
  void *p = malloc(n);
  if (p == NULL && n > 0) {
    printf("Memory allocation has failed");
    exit(EXIT_FAILURE);
  }
  return p;
}

// or insure `malloc(0)` never occurs.

void *malloc_check(size_t n) {
  if (n == 0) n++;
  void *p = malloc(n);
  if (p == NULL) {
    printf("Memory allocation has failed");
    exit(EXIT_FAILURE);
  }
  return p;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    相关资源
    最近更新 更多