在免费呼叫之前检查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的原因有两个:
-
因为变量用于类型理论中被称为选项类型的东西 ,并且包含指向对象的指针,或者NULL表示什么都没有 ,
-
因为它指向一个数组,因此如果数组的长度为零,则可能为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! ...
但如果它不明显,那么断言可能值得键入字符。