释放指针重新自我调整?

时间:2015-09-23 13:36:08

标签: c struct structure dynamic-allocation

当我动态分配一个结构,然后尝试释放它时,它似乎重新分配它。

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

所以在释放并清空指针之后,如果我再次检查它,它会回到原来的状态。那是问题吗?或者它是免费的,我不再需要担心它了吗?

4 个答案:

答案 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. 丢失对原始malloc指针的引用
  2. 尝试释放堆栈中的对象
  3. 将0分配给指针的副本(传递给freeup)
  4. (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检查等以使代码更清晰,但它们肯定应该存在。