为什么不将free(p)设置为NULL?

任何原因导致这不能成为free()标准行为?

多个指针指向同一个对象:

 #include  #include  void safefree(void*& p) { free(p); p = NULL; } int main() { int *p = (int *)malloc(sizeof(int)); *p = 1234; int*& p2 = p; printf("p=%p p2=%p\n", p, p2); safefree((void*&)p2); printf("p=%p p2=%p\n", p, p2); safefree((void*&)p); // safe return 0; } 

来自malloc赋值要求从void*

反之亦然:

safefree()要求转换为void*& (参考)

如果是,则必须将指针传递给指向函数的指针:

 int * p = malloc( sizeof( int )); free( & p ); 

我相信很多人会出错。

简单回答:因为你可能正在释放一个表达式,例如free(find_named_object("foo"))

更详细: free函数接受一个void*参数,该参数是要释放的内存的地址。 这并不赋予函数任何提供地址的原始变量的知识(或者,就此而言,是否存在变量)。 只是将传入的参数设置为NULL也不会做任何事情,因为它只是地址的本地副本。

Bjarne Stroustrup 讨论delete操作符是否应该将其操作数置零 。 它不是free()函数,但无论如何它都是一个很好的讨论。 考虑以下几点:

  • 如果你说免费(p + 1)会被归零吗?
  • 如果内存有两个指针怎么办? 为什么只有悬挂参考仍然留下时才设置为null?

他还说这是有意的,但从未发生过operator delete

C ++显然允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎。

C函数参数总是按值传递,因此为了修改传递给free()的指针,您需要将指针传递给正被释放的指针,这可能会导致忘记&运算符导致的错误。

其次,如果该指针有任何别名,程序员仍然负责将它们归零。 我可以看到程序员假设所有引用都设置为NULL而导致的问题。

最后,并不总是需要将指针设置为NULL。 想象一个function,它分配一些内存,做一些工作,并在返回之前释放它。 我可以看到如何将指针设置为NULL似乎不是最佳的。

因为函数参数是用C中的值传递的。也就是说,如果p == 0x12345,你将’0x12345’传递给free(),而不是p“本身”。

参考Stroustrup关于删除的引用,Peter Norvig也发表了类似的评论。 他写道(不是关于C ++!):

 "Nothing is destroyed until it is replaced" - Auguste Comte (1798-1857) (on the need for revolutionary new theories (or on the need to do xf = null in garbage-collected languages with destructors)) 

在我的C代码中,我发现以下宏非常有用:

 #define free(p) free((void *)(p)),(p)=NULL /* zero p */ 

正如所写,这两次使用它的论点。 但这不是问题,因为任何用法(例如free(p ++)或free(find_named_object(“foo”))都会产生编译时错误(需要左值)。 你可以通过使用(免费)(p ++)隐藏宏,或者通过调用其他东西,例如FREE。

在C中,调用一个函数永远不会改变你传入的参数的值,所以如果free(p)通过将p的值设置为NULL来改变它的值,那么这种行为确实非常不标准。

将引用从int *&void *& 保证可以正常工作。 int *根本不必具有与void *相同的大小,表示和对齐要求。

正如Neil Butterworth在评论中所建议的那样,正确的C ++解决方案将是使用模板。 这些方式都不适用于C,显然 – 这就是free()来自哪里。

什么是零的疯狂的事情? 还有其他数字!

为什么自由指针应该包含多于零的任何其他值?

实际上,在我的C ++代码中,我经常使用看门狗对象,当释放指针时,将其重置为零而不是看门狗。 这有一个额外的好处,即仍然可以使用现有接口调用对象的方法,并且将指针重置为零更安全有效(它避免将对象测试为零,我只是调用对象)。

如果一个自由的函数说zfree(void *&p)将p设置为零,它将禁止我的看门狗风格(或者至少不会有帮助)。

当其他指针指出时,如果指针超出范围,将指针重置为零会有什么意义呢? 只是无用的代码。 如果有其他指针包含相同的地址,等等怎么办?