释放指针重新分配自身?
Freed pointer reallocaing itself?
当我动态分配一个结构,然后尝试释放它时,它似乎重新分配了它。
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
因此,在释放并清空指针后,如果我再次检查它,它会恢复到原来的状态。那是问题吗?或者它是免费的,我再也不用担心了?
首先,这一行是在堆栈上分配foo
,然后将动态分配的结构复制到这个地方:
OBJ foo = *Construct(10, 20);
当然,您不应该释放它。正确的大小写是:
OBJ* foo = Construct(10, 20);
. . .
freeup(foo);
其次,如果要清除freeup
中的指针,则将参数类型改为pointer-to-pointer:
void freeup(OBJ** x)
{
free(*x);
*x=NULL;
}
...在这种情况下,您应该将 freeup
调用更改为 freeup(&foo);
。
最后,foo
似乎在您的代码中重新分配了,但它不能被释放或分配,它是一个堆栈变量。所以指向 foo
的指针在函数内部总是相同的。
您在行中丢失了指针
OBJ foo = *Construct(10, 20);
你将 Construct
编辑的指针 return 指向的结构体 OBJ
复制到 foo
中,然后丢弃指针。
在那之后,因为你没有指针,你没有办法释放由 Constructor
.
分配的实际 struct OBJ
你的 freeup
调用是错误的,因为你试图释放 foo
,而不是原来的。
正确的方法是继续使用指针,所以
OBJ *foo = Construct(10, 20);
...
freeup(foo);
或者根本不使用指针,只是 return Construct
中的 OBJ
,而不是 OBJ*
。这样,就不用担心释放任何东西了。
OBJ foo = *Construct(10, 20);
因此,您丢失了指向由 malloc
分配的块的指针。因此 free
ing 内存未由 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);
您的代码中存在多个问题:
- 失去对原始 malloc 指针的引用
- 正在尝试释放堆栈上的对象
- 将 0 分配给指针的副本(传递给 freeup)
(1) OBJ foo = *Construct(10, 20);
行没有将指向分配的 OBJ 的指针赋值给 foo,而是将 OBJ
的值复制到堆栈,到一个名为 foo 的变量,这导致您丢失对已分配对象的引用(并导致内存泄漏)。
一个更好的方法是return指针本身,它更清晰,不会导致你丢失引用,而且效率更高:
OBJ *foo = Construct(10, 20);
现在 foo 是指向对象的指针,而不是对象本身。
(2) 从 (1) 派生,现在我们使用 foo 作为指向 malloc 对象的指针,我们可以在其上使用 free。
(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 检查等,但它们绝对应该存在。
当我动态分配一个结构,然后尝试释放它时,它似乎重新分配了它。
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
因此,在释放并清空指针后,如果我再次检查它,它会恢复到原来的状态。那是问题吗?或者它是免费的,我再也不用担心了?
首先,这一行是在堆栈上分配foo
,然后将动态分配的结构复制到这个地方:
OBJ foo = *Construct(10, 20);
当然,您不应该释放它。正确的大小写是:
OBJ* foo = Construct(10, 20);
. . .
freeup(foo);
其次,如果要清除freeup
中的指针,则将参数类型改为pointer-to-pointer:
void freeup(OBJ** x)
{
free(*x);
*x=NULL;
}
...在这种情况下,您应该将 freeup
调用更改为 freeup(&foo);
。
最后,foo
似乎在您的代码中重新分配了,但它不能被释放或分配,它是一个堆栈变量。所以指向 foo
的指针在函数内部总是相同的。
您在行中丢失了指针
OBJ foo = *Construct(10, 20);
你将 Construct
编辑的指针 return 指向的结构体 OBJ
复制到 foo
中,然后丢弃指针。
在那之后,因为你没有指针,你没有办法释放由 Constructor
.
struct OBJ
你的 freeup
调用是错误的,因为你试图释放 foo
,而不是原来的。
正确的方法是继续使用指针,所以
OBJ *foo = Construct(10, 20);
...
freeup(foo);
或者根本不使用指针,只是 return Construct
中的 OBJ
,而不是 OBJ*
。这样,就不用担心释放任何东西了。
OBJ foo = *Construct(10, 20);
因此,您丢失了指向由 malloc
分配的块的指针。因此 free
ing 内存未由 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);
您的代码中存在多个问题:
- 失去对原始 malloc 指针的引用
- 正在尝试释放堆栈上的对象
- 将 0 分配给指针的副本(传递给 freeup)
(1) OBJ foo = *Construct(10, 20);
行没有将指向分配的 OBJ 的指针赋值给 foo,而是将 OBJ
的值复制到堆栈,到一个名为 foo 的变量,这导致您丢失对已分配对象的引用(并导致内存泄漏)。
一个更好的方法是return指针本身,它更清晰,不会导致你丢失引用,而且效率更高:
OBJ *foo = Construct(10, 20);
现在 foo 是指向对象的指针,而不是对象本身。
(2) 从 (1) 派生,现在我们使用 foo 作为指向 malloc 对象的指针,我们可以在其上使用 free。
(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 检查等,但它们绝对应该存在。