在调用free之前检查NULL

时间:2009-12-16 04:39:07

标签: c

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

if (p)
  free(p);

但为什么呢?我认为C标准说free函数在给定NULL指针时不执行任何操作。那么为什么要另外明确检查呢?

8 个答案:

答案 0 :(得分:18)

构造:

free(NULL);

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

答案 1 :(得分:13)

据我所知,NULL上的无操作并不总是存在。

  

在C的糟糕的旧时代(回到周围   1986年,以ANSI标准cc为准   编译器)free(NULL)会转储核心。   所以大多数开发人员之前都测试过NULL / 0   免费打电话。

     

世界已经走过了漫长的道路   似乎我们不需要这样做   再试一次。但旧习惯会死亡   硬;)

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

答案 2 :(得分:6)

我倾向于写“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);

我知道,这不是一个理性的原因,但那是我的理由:)

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

  1. 因为该变量用于类型理论中称为选项类型的变量,并且包含指向对象的指针,或者用于表示 nothing 的NULL ,

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

  3. 虽然这只是一个逻辑上的区别(在C中既没有选项类型也没有特殊的指向数组的指针而我们只是使用指针来处理所有内容),它应该始终是明确了如何使用变量。

    C标准要求free(NULL)不执行任何操作是成功调用malloc(0)可能返回NULL这一事实的必要对应物。这不是一般的便利,这就是为什么例如fclose() 需要非NULL参数的原因。通过传递一个不代表零长度数组的NULL来滥用调用free(NULL)的权限会让人产生hackish和错误。

答案 6 :(得分:0)

如果依赖于free(0)是OKAY,并且此时指针为空是正常的,请在评论// may be NULL

中说明

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

答案 7 :(得分:0)

if (p)
    free(p);
     

为什么要另外明确检查?

如果写了类似的东西,那就传达指针可能为NULL的特定知识......以帮助提高可读性和代码理解能力。因为使断言变得有点奇怪:

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

(除了看起来很奇怪,众所周知编译器会抱怨"条件总是正确的"如果你在许多这样的情况下提出你的警告。)

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

相反的情况,指针应该是 null,通常可以从前面的代码行中看出:

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

但如果它不明显,那么断言可能值得键入字符。