C语言 free 对按值传递给函数的指针做什么



众所周知,如果我们按值将指针传递给函数,则无法在函数内部释放它,如下所示:

void func(int *p)
{
    free(p);
    p = NULL;
}
p

持有一个(大概有效)地址的副本,所以 free(p) 试图释放它。但由于它是副本,因此无法真正释放它。对free()的调用如何知道它不能真正释放它?

上面的代码不会产生错误。这是否意味着free()只是静默地失败,"不知何故"知道作为参数传入的地址无法处理?

p

持有一个(大概有效)地址的副本,所以 free(p) 试图释放它。但由于它是副本,因此无法真正释放它。

这不是真的。 如果pmalloc()(或NULL)返回的有效地址,free()可以正常工作。

事实上,这是实现自定义"析构函数"函数的常见模式(在用 C 语言编写 OO 样式代码时)。

您可能的意思是,在此之后p不会更改为NULL - 但这很自然,因为您是通过值传递它。如果要free()清空指针,则通过指针("byref")传递它:

void func(int **p)
{
    if (p != NULL) {
        free(*p);
        *p = NULL;
    }
}

并像这样使用它

int *p = someConstructor();
func(&p);
// here 'p' will actually be NULL

唯一的问题是这个函数是否在不同的DLL(Windows)中。然后,它可能与不同版本的标准库链接,并对如何构建堆有不同的想法。

否则没问题。

按值将p传递给func(),这将复制指针并创建本地副本,以释放内存func()。 然后,func()将自己的指针实例设置为p NULL但无用。函数完成后,参数p结束存在。在调用函数中,您仍然有指针p保存地址,但该块现在在空闲列表中,并且在再次分配之前对存储没有用处。

每个人都在说你的内存会被free(p);释放,但你的原始指针(你用来调用函数)仍然会保存(现在无效的)地址。如果在比原始指针更晚的阶段分配了包含地址的新内存块,则会再次生效(对于内存管理器),但现在将指向完全不同的数据,从而导致各种问题和混乱。

不,

你真的释放了内存块。在函数调用之后,传递给此函数的指针指向无处:相同的地址,但MMU不再知道如何处理此地址

最新更新