【问题标题】:checking for NULL before calling free在免费调用之前检查 NULL
【发布时间】:2010-12-27 02:34:25
【问题描述】:

许多 C 代码释放指针调用:

if (p)
  free(p);

但是为什么呢?我认为 C 标准说 free 函数在给定 NULL 指针的情况下不会做任何事情。那么为什么还要进行一次显式检查呢?

【问题讨论】:

  • 因为人们不知道C标准?
  • 这就是“ish”的所在。所以我应该说,即使它不是重复的,那篇文章也可能很有趣。
  • @zaharpopov:我在 615355 中添加了 c++。

标签: c allocation


【解决方案1】:
if (p)
    free(p);

为什么还要进行明确的检查?

如果写这样的东西,它是为了传达指针可能为NULL的特定知识......以帮助可读性和代码理解。因为将其设为断言看起来有点奇怪:

assert(p || !p);
free(p);

(除了看起来很奇怪之外,众所周知,如果您在许多此类情况下打开警告,编译器会抱怨“条件始终为真”。)

所以我认为这是一种很好的做法,如果从上下文中不清楚的话。

从前面的代码行中通常可以明显看出指针被预期为 non null 的相反情况:

...
Unhinge_Widgets(p->widgets);
free(p); // why `assert(p)`...you just dereferenced it!
...

但如果它不是显而易见的,那么有断言可能值得输入字符。

【讨论】:

    【解决方案2】:

    指针变量可能为 NULL 的原因有两个:

      1234563 ,
    1. 因为它指向一个数组,因此如果数组长度为零,则可能为 NULL(因为malloc(0) 允许返回 NULL,实现定义)。

    虽然这只是逻辑上的区别(在 C 中,既没有选项类型,也没有特殊的指向数组的指针,我们只是对所有事物都使用指针),但它应该始终是明确如何使用变量。

    C 标准要求free(NULL) 什么都不做是对malloc(0) 的成功调用可能返回NULL 的必要对应。这并不意味着一般的方便,这就是为什么例如fclose() 确实需要一个非NULL参数。通过传递一个不代表零长度数组的 NULL 来滥用调用 free(NULL) 的权限让人感觉既不礼貌又是错误的。

    【讨论】:

      【解决方案3】:

      编译器,即使内联不够聪明,无法知道函数会立即返回。将参数等推入堆栈并设置调用显然比测试指针更昂贵。我认为避免执行任何事情总是好的做法,即使任何事情都是无操作的。 测试 null 是一种很好的做法。更好的做法是确保您的代码不会达到这种状态,从而完全消除对测试的需要。

      【讨论】:

      • 面对错误预测的分支不再明显。
      【解决方案4】:

      构造:

      free(NULL);
      

      在 C 语言中一直没问题,回到 Dennis Ritchie 编写的原始 UNIX 编译器。预标准化,一些糟糕的编译器可能没有正确使用它,但是现在任何编译器都不能合法地称自己为 C 语言的编译器。使用它通常会导致代码更清晰、更易于维护。

      【讨论】:

        【解决方案5】:

        在移动环境中可以自定义实现 free()。 在这种情况下 free(0) 可能会导致问题。 (是的,糟糕的实现)

        【讨论】:

        • 一个新的 C 实现,当今天开始时,没有任何借口产生这样的错误。 C 标准在这一点上很明确。
        • @vog:独立实现根本不需要提供malloc()free(),但通常允许用户代码定义他们认为合适的功能。即使存在#define free(x) customReleaseThatDoesntLikeNull(x),包括显式的空检查也会使代码正常工作。
        【解决方案6】:

        如果您认为 free(0) 是可以的,此时您的指针为空是正常的,请在评论中说明// may be NULL

        这可能只是不言自明的代码,说是的,我知道,我也使用 p 作为标志

        【讨论】:

          【解决方案7】:

          我倾向于写很多“if (p) free(p)”,即使我知道它没有必要。

          我部分责备自己,因为我在过去学习 C 时 free(NULL) 会出现段错误,但我仍然觉得不这样做很不舒服。

          但我也指责 C 标准不一致。例如,fclose(NULL) 是否可以很好地定义,我不会有写作问题:

          free(p);
          fclose(f);
          

          这是清理东西时经常发生的事情。 不幸的是,我觉得写起来很奇怪

          free(p);
          if (f) fclose(f);
          

          我最终得到了

          if (p) free(p);
          if (f) fclose(f);
          

          我知道,这不是一个合理的原因,但这是我的情况:)

          【讨论】:

          • 是的,这个答案指出了 C 语言缺乏一致性,实际上程序员跟踪正确做法是开销。
          【解决方案8】:

          据我了解,NULL 的无操作并不总是存在。

          在 C 的糟糕的旧时代(回到过去 1986 年,基于 pre-ANSI 标准 cc 编译器)free(NULL)将转储核心。 所以大多数开发人员之前都测试过 NULL/0 免费通话。

          世界已经走过了漫长的道路,它 看来我们不需要这样做 测试了。但是旧习惯会消失 硬;)

          http://discuss.joelonsoftware.com/default.asp?design.4.194233.15

          【讨论】:

          • +1 这是我记得的,但我找不到它的参考。
          • 据我了解,即使在标准化之后,一些编译器也存在这个缺陷。
          • 它一直存在,即使在最初的 UNIX 实现中也是如此。 P.J. Plauger 关于标准化过程的文章中提到了这一点 - 但目前无法找到确切的参考。
          • 乔尔被引用为技术权威的那一天对人类来说是可悲的一天。
          • Neil:这是来自 joel 网站论坛的引述,实际引述不是来自他,而是来自一个名叫 Guidii 的人。所以我认为今天人类已经得救了
          猜你喜欢
          • 2010-10-07
          • 1970-01-01
          • 2017-06-24
          • 1970-01-01
          • 2014-02-02
          • 1970-01-01
          • 2012-05-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多