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

c++ c memory-management memory-leaks free

4819 观看

9回复

3376 作者的声誉

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

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

#include <stdlib.h>
#include <stdio.h>

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*&(参考)

作者: Oleg Razgulyaev 的来源 发布者: 2010 年 4 月 16 日

回应 (9)


27

148821 作者的声誉

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

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

作者: Marcelo Cantos 发布者: 16.04.2010 09:35

28

0 作者的声誉

决定

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

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

我相信很多人会错的。

作者: anon 发布者: 16.04.2010 09:37

5

46319 作者的声誉

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

作者: user187291 发布者: 16.04.2010 09:37

2

49443 作者的声誉

在C中,调用函数永远不会改变传入的参数的值,因此如果通过将其设置为free(p)更改值,那么这种行为确实非常不标准。pNULL

作者: Paul Stephenson 发布者: 16.04.2010 09:38

7

82206 作者的声誉

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

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

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

作者: Ferruccio 发布者: 16.04.2010 09:50

15

17122 作者的声誉

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

  • 如果你说免费(p + 1)会被归零吗?
  • 如果内存有两个指针怎么办?如果仍然留下悬空引用,为什么只将一个设置为null?

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

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

2

7278 作者的声誉

参考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 x.f = 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。

作者: Joseph Quinsey 发布者: 16.04.2010 05:21

0

197061 作者的声誉

铸造从基准int *&void *&保证工作。 int *根本不必具有相同的大小,表示和对齐要求void *

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

作者: caf 发布者: 16.04.2010 11:37

0

17177 作者的声誉

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

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

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

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

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

作者: kriss 发布者: 13.07.2010 11:18
32x32