许多 C 代码释放指针调用:
if (p)
free(p);
但为什么?我认为 C 标准说该free
函数在给定 NULL 指针的情况下不做任何事情。那么为什么要进行另一个明确的检查呢?
许多 C 代码释放指针调用:
if (p)
free(p);
但为什么?我认为 C 标准说该free
函数在给定 NULL 指针的情况下不做任何事情。那么为什么要进行另一个明确的检查呢?
构造:
free(NULL);
在 C 语言中一直没问题,回到 Dennis Ritchie 编写的原始 UNIX 编译器。预标准化,一些糟糕的编译器可能没有正确使用它,但是现在任何编译器都不能合法地称自己为 C 语言的编译器。使用它通常会导致更清晰、更易于维护的代码。
据我了解,NULL 上的无操作并不总是存在。
在 C 的糟糕旧时代(早在 1986 年左右,在 ANSI 标准之前的 cc 编译器上)free(NULL) 会转储核心。所以大多数开发人员在免费调用之前测试了 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 是一种很好的做法。更好的做法是确保您的代码不会达到这种状态,从而完全消除对测试的需要。
指针变量可能为 NULL 的原因有两个:
因为该变量用于在类型理论中称为选项类型,并且保存指向对象的指针,或者 NULL 表示什么都没有,
因为它指向一个数组,因此如果数组长度为零(malloc(0)
允许返回 NULL,实现定义),则它可能为 NULL。
尽管这只是逻辑上的区别(在 C 中既没有选项类型也没有指向数组的特殊指针,我们只是对所有内容都使用指针),但始终应该清楚如何使用变量。
C 标准要求什么都不做是成功调用可能返回free(NULL)
这一事实的必要对应物。这并不意味着一般的便利,这就是为什么例如确实需要非 NULL 参数的原因。通过传递不代表零长度数组的 NULL来滥用调用权限会让人感觉很糟糕和错误。malloc(0)
NULL
fclose()
free(NULL)
如果您依赖 free(0) 就可以了,此时您的指针为空是正常的,请在评论中说明// may be NULL
这可能只是不言自明的代码,说是的,我知道,我也使用 p 作为标志。
在移动环境中可以有一个自定义的 free() 实现。在这种情况下 free(0) 可能会导致问题。(是的,糟糕的实施)
if (p) free(p);
为什么要进行另一个明确的检查?
如果我写这样的东西,它是为了传达指针可能为 NULL 的特定知识......以帮助可读性和代码理解。因为让它成为一个断言看起来有点奇怪:
assert(p || !p);
free(p);
(除了看起来很奇怪之外,如果您在许多此类情况下打开警告,编译器会抱怨“条件始终为真”。)
所以我认为这是一种很好的做法,如果从上下文中不清楚的话。
从前面的代码行中通常可以明显看出指针被期望为非空的相反情况:
...
Unhinge_Widgets(p->widgets);
free(p); // why `assert(p)`...you just dereferenced it!
...
但如果它不明显,那么拥有断言可能值得输入字符。