在免费呼叫之前检查NULL

时间:2022-02-04 19:20:46

Many C code freeing pointers calls:

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

if (p)
  free(p);

But why? I thought C standard say the free function doesn't do anything given a NULL pointer. So why another explicit check?

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

8 个解决方案

#1


18  

The construct:

结构:

free(NULL);

has always been OK in C, back to the original UNIX compiler written by Dennis Ritchie. Pre-standardisation, some poor compilers might not have fielded it correctly, but these days any compiler that does not cannot legitimately call itself a compiler for the C language. Using it typically leads to clearer, more maintainable code.

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

#2


13  

As I understand, the no-op on NULL was not always there.

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

In the bad old days of C (back around 1986, on a pre-ANSI standard cc compiler) free(NULL) would dump core. So most devs tested for NULL/0 before calling free.

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

The world has come a long way, and it appears that we don't need to do the test anymore. But old habits die hard;)

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

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

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

#3


4  

I tend to write "if (p) free(p)" a lot, even if I know it's not needed.

我倾向于写“if(p)free(p)”,即使我知道它不需要。

I partially blame myself because I learned C the old days when free(NULL) would segfault and I still feel uncomfortable not doing it.

我部分地责备自己,因为我学习了C过去的时候,免费(NULL)会出现段错误,我仍然觉得不舒服。

But I also blame the C standard for not being consistent. Would, for example, fclose(NULL) be well defined, I would not have problems in writing:

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

free(p);
fclose(f);

Which is something that happens very often when cleaning up things. Unfortunately, it seems strange to me to write

在清理东西时经常会发生这种情况。不幸的是,写作似乎很奇怪

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

and I end up with

我最终得到了

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

I know, it's not a rational reason but that's my case :)

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

#4


2  

Compilers, even when inlining are not smart enough to know the function will return immediately. Pushing parameters etc on stack and setting the call up up is obviously more expensive than testing a pointer. I think it is always good practice to avoid execution of anything, even when that anything is a no-op. Testing for null is a good practice. An even better practice is to ensure your code does not reach this state and therefore eliminate the need for the test altogether.

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

#5


1  

there can be a custom implementation of free() in mobile environment. In that case free(0) can cause a problem. (yeah, bad implementation)

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

#6


1  

There are two distinct reasons why a pointer variable could be NULL:

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

  1. because the variable is used for what in type theory is called an option type, and holds either a pointer to an object, or NULL to represent nothing,

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

  2. because it points to an array, and may therefore be NULL if the array has zero length (as malloc(0) is allowed to return NULL, implementation-defined).

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

Although this is only a logical distinction (in C there are neither option types nor special pointers to arrays and we just use pointers for everything), it should always be made clear how a variable is used.

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

That the C standard requires free(NULL) to do nothing is the necessary counterpart to the fact that a successful call to malloc(0) may return NULL. It is not meant as a general convenience, which is why for example fclose() does require a non-NULL argument. Abusing the permission to call free(NULL) by passing a NULL that does not represent a zero-length array feels hackish and wrong.

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

#7


0  

If you rely on that free(0) is OKAY, and it's normal for your pointer to be null at this point, please say so in comment // may be NULL

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

This may be merely self-explanatory code, saying yes I know, I also use p as a flag.

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

#8


0  

if (p)
    free(p);

why another explicit check?

为什么另一个明确检查

If I write something like that, it's to convey the specific knowledge that the pointer may be NULL...to assist in readability and code comprehension. Because it looks a bit weird to make that an assert:

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

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

(Beyond looking strange, compilers are known to complain about "condition always true" if you turn your warnings up in many such cases.)

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

So I see it as good practice, if it's not clear from the context.

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

The converse case, of a pointer being expected to be non null, is usually evident from the previous lines of code:

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

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

But if it's non-obvious, having the assert may be worth the characters typed.

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

#1


18  

The construct:

结构:

free(NULL);

has always been OK in C, back to the original UNIX compiler written by Dennis Ritchie. Pre-standardisation, some poor compilers might not have fielded it correctly, but these days any compiler that does not cannot legitimately call itself a compiler for the C language. Using it typically leads to clearer, more maintainable code.

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

#2


13  

As I understand, the no-op on NULL was not always there.

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

In the bad old days of C (back around 1986, on a pre-ANSI standard cc compiler) free(NULL) would dump core. So most devs tested for NULL/0 before calling free.

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

The world has come a long way, and it appears that we don't need to do the test anymore. But old habits die hard;)

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

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

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

#3


4  

I tend to write "if (p) free(p)" a lot, even if I know it's not needed.

我倾向于写“if(p)free(p)”,即使我知道它不需要。

I partially blame myself because I learned C the old days when free(NULL) would segfault and I still feel uncomfortable not doing it.

我部分地责备自己,因为我学习了C过去的时候,免费(NULL)会出现段错误,我仍然觉得不舒服。

But I also blame the C standard for not being consistent. Would, for example, fclose(NULL) be well defined, I would not have problems in writing:

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

free(p);
fclose(f);

Which is something that happens very often when cleaning up things. Unfortunately, it seems strange to me to write

在清理东西时经常会发生这种情况。不幸的是,写作似乎很奇怪

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

and I end up with

我最终得到了

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

I know, it's not a rational reason but that's my case :)

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

#4


2  

Compilers, even when inlining are not smart enough to know the function will return immediately. Pushing parameters etc on stack and setting the call up up is obviously more expensive than testing a pointer. I think it is always good practice to avoid execution of anything, even when that anything is a no-op. Testing for null is a good practice. An even better practice is to ensure your code does not reach this state and therefore eliminate the need for the test altogether.

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

#5


1  

there can be a custom implementation of free() in mobile environment. In that case free(0) can cause a problem. (yeah, bad implementation)

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

#6


1  

There are two distinct reasons why a pointer variable could be NULL:

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

  1. because the variable is used for what in type theory is called an option type, and holds either a pointer to an object, or NULL to represent nothing,

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

  2. because it points to an array, and may therefore be NULL if the array has zero length (as malloc(0) is allowed to return NULL, implementation-defined).

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

Although this is only a logical distinction (in C there are neither option types nor special pointers to arrays and we just use pointers for everything), it should always be made clear how a variable is used.

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

That the C standard requires free(NULL) to do nothing is the necessary counterpart to the fact that a successful call to malloc(0) may return NULL. It is not meant as a general convenience, which is why for example fclose() does require a non-NULL argument. Abusing the permission to call free(NULL) by passing a NULL that does not represent a zero-length array feels hackish and wrong.

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

#7


0  

If you rely on that free(0) is OKAY, and it's normal for your pointer to be null at this point, please say so in comment // may be NULL

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

This may be merely self-explanatory code, saying yes I know, I also use p as a flag.

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

#8


0  

if (p)
    free(p);

why another explicit check?

为什么另一个明确检查

If I write something like that, it's to convey the specific knowledge that the pointer may be NULL...to assist in readability and code comprehension. Because it looks a bit weird to make that an assert:

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

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

(Beyond looking strange, compilers are known to complain about "condition always true" if you turn your warnings up in many such cases.)

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

So I see it as good practice, if it's not clear from the context.

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

The converse case, of a pointer being expected to be non null, is usually evident from the previous lines of code:

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

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

But if it's non-obvious, having the assert may be worth the characters typed.

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