所以我试图理解C中的内存管理的整个概念,我得到了这段代码:
int main(int argc, int *argv[]) {
item *x = NULL;
x = (item *) malloc (sizeof(item));
...
free_item(&x);
}
void free_item(item **x) {
free(*x);
*x = NULL;
}
其中item
是早期定义的结构。我感到困惑的地方是free_item(&x);
,因为当我写free_item(x);
并将函数更改为:
void free_item(item *x) {
free(x);
x = NULL;
}
代码似乎与前一代码的工作方式相同。
那么,有什么区别吗?如果没有,是否有任何理由,为什么有人会将一个结构指针的地址发送给一个函数,从而释放这个结构?
答案 0 :(得分:3)
是。首先,我认为你修改过的函数中有一个拼写错误。它应该是:
void free_item(item *x) {
free(x);
x = NULL;
}
现在,为了差异。 free
调用将成功,因为它所期望的是一个"指向类型的指针"在堆上动态分配的数据的变量。
第二部分x = NULL
将无法按预期工作。请记住,在C中,当将参数传递给函数时,我们总是按值传递,而不是通过引用传递。您正在传递变量的副本,因此x = NULL
只会将x
临时自动分配的副本设置为NULL
,而不是作为传递的实际变量参数。
您更改的原始功能正确地完成了两个部分。
答案 1 :(得分:0)
在第一种情况下,要修改指针变量content
的{{1}},您需要使用引用传递。这就是x
和双指针被用于&x
从free()
分配的记忆的原因。这是正确的。
在第二种情况下,将创建main()
的函数本地副本并将其传递给x
,这对free_item()
中的x
没有影响}}。 main()
的范围仅在x = NULL;
内。
答案 2 :(得分:0)
在您的第一个示例中,您使用类型指针的参数调用free_item
指向项目的指针(假设item **x
参数)。
在第二个示例中,将点值(main::x
)复制到free_item::x
(不同范围),并将复制的值设置为NULL
(之后丢弃值)。
将printf("%p\n", x);
添加到main()
的末尾(free_item
之后)。
在第一个示例中,您会看到NULL
,第二个x
仍会设置为先前存储在那里的地址。
在第一个示例中,假设您的指针位于地址0x00400000
上,它指向在0x00410000
分配的内存。
0x00400000 0x00410000 <- x is stored here
0x00400004 0x00400000 <- tmp described later; point to x
...
0x00410000 .......... <- x points here; start of item - returned by malloc
当您致电item **tmp = &x
时,您会看到它将包含地址0x00400000
(并且tmp
本身将存储在不同的内存地址中。)
然后在free_item()
:
free(*tmp); // The same as free(0x00410000)
*tmp = NULL; // Modifies data at 0x00400000 = NULL
答案 3 :(得分:-1)
使用free时,传递指针,而不是指针的值。
所以,如果你使用
item *x
,你应该使用
free(x)
答案 4 :(得分:-2)
x = (item *) malloc (sizeof(item));
是不必要的。 x = malloc(sizeof(item));
就足够了。2
void free_item(item *data){
free(data);
}
这是正确的方法。
我会写free_item(x);
而不是free_item(&x)
并且free_item(item **x)