当我动态分配一个结构,然后尝试释放它时,它似乎重新分配它。
typedef struct OBJ_T
{
int param1, param2;
} OBJ;
OJB* Construct(int par1, int par2)
{
OBJ* x = malloc(sizeof(OBJ));
x->param1 = par1;
x->param2 = par2;
return x;
}
void freeup(OBJ *x)
{
printf("x pointer -> %d ", x);
free(x);
x=NULL;
printf("\nx pointer -> %d\n", x);
}
int main()
{
OBJ foo = *Construct(10, 20);
freeup(&foo);
freeup(&foo);
return 0;
}
结果是:
x pointer -> 2752216
x pointer -> 0
x pointer -> 2752216
x pointer -> 0
所以在释放并清空指针之后,如果我再次检查它,它会回到原来的状态。那是问题吗?或者它是免费的,我不再需要担心它了吗?
答案 0 :(得分:4)
首先,此行在堆栈上分配foo
,然后将动态分配的结构复制到该位置:
OBJ foo = *Construct(10, 20);
原因是,你不应该释放它。正确的案例是:
OBJ* foo = Construct(10, 20);
. . .
freeup(foo);
其次,如果要清除freeup
中的指针,则将参数类型更改为指向指针:
void freeup(OBJ** x)
{
free(*x);
*x=NULL;
}
...在这种情况下,您应该将freeup
来电更改为freeup(&foo);
。
最后,似乎foo
在您的代码中被重新分配,但它不能被释放或分配,它是一个堆栈变量。因此,指向foo
的指针在函数内总是相同的。
答案 1 :(得分:2)
你正在丢失你的指针
OBJ foo = *Construct(10, 20);
您将OBJ
返回的指针指向的结构Construct
,将其值复制到foo
,然后扔掉指针。
之后,由于您没有指针,因此您无法释放由struct OBJ
分配的实际Constructor
。
您的freeup
来电是错误的,因为您尝试释放foo
,而不是原始。
正确的方法是继续使用指针,所以
OBJ *foo = Construct(10, 20);
...
freeup(foo);
或根本不使用指针,只返回OBJ
中的Construct
,而不是OBJ*
。这样,就没有必要担心放任何东西了。
答案 2 :(得分:1)
OBJ foo = *Construct(10, 20);
由于这个原因,你丢失指向由malloc
分配的块的指针。所以free
内存未由malloc
分配或类似导致程序错误。
这个我真的不明白(一般来说 - 也不应该用指针完成) -
freeup(&foo); // just one call is enough
freeup(&foo); // Why twice ?
而这 -
void freeup(OBJ *x)
{
printf("x pointer -> %d ", x);
free(x);
x=NULL;
printf("\nx pointer -> %d\n", x); // should not be done in any case after assigning pointer to NULL
}
你可以这样做 -
void freeup(OBJ **x)
{
printf("x pointer -> %d ", *x);
free(*x);
*x = NULL;
}
以与freeup(&foo);
答案 3 :(得分:1)
您的代码中存在多个问题:
(1)行OBJ foo = *Construct(10, 20);
不会将指向已分配的OBJ的指针分配给foo,而是将OBJ
的值复制到堆栈,复制到名为foo的变量,这会导致你丢失对已分配对象的引用(并导致内存泄漏)。
更好的方法是返回指针本身,它更清晰,不会导致您丢失引用,并且效率更高:
OBJ *foo = Construct(10, 20);
现在foo是指向对象的指针,而不是对象本身。
(2)派生自(1),现在我们使用foo作为指向malloc'd对象的指针,我们可以免费使用它。
(3)从被调用者分配参数不会更改调用者站点中的值。这称为pass-by-value,因为只有参数值的副本传递给被调用者。所以让我们改变freeup
:
void freeup(OBJ **x)
{
printf("x pointer -> %d ", *x);
free(*x);
*x=NULL;
printf("\nx pointer -> %d\n", *x);
}
这样,调用者站点上指针的值就会改变。
请注意,我省略了NULL检查等以使代码更清晰,但它们肯定应该存在。