在免费呼叫之前检查NULL

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

if (p) free(p); 

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

结构:

 free(NULL); 

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

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

在C的糟糕时期(早在1986年,在ANSI标准cc编译器之前),free(NULL)将转储核心。 所以大多数开发人员在调用free之前测试了NULL / 0。

世界已经走过了漫长的道路,似乎我们不再需要进行测试了。 但是旧习惯很难改变;)

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

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

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

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

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

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

  1. 因为变量用于类型理论中被称为选项类型的东西 ,并且包含指向对象的指针,或者NULL表示什么都没有

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

虽然这只是一个逻辑上的区别(在C中既没有选项类型也没有指向数组的特殊指针 ,我们只使用指针表示所有内容),应该始终清楚如何使用变量。

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

如果您依赖于free(0)是OKAY,并且此时指针为null是正常的,请在注释中说明// may be NULL

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

 if (p) free(p); 

为什么另一个明确检查

如果写这样的东西,那就是传达指针可能为NULL的特定知识……以帮助提高可读性和代码理解能力。 因为断言这看起来有点奇怪:

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

(除了看起来很奇怪之外,如果你在很多这样的情况下发出警告,编程器就会抱怨“情况总是如此”。)

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

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

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

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