从C中的其他函数内部释放指针

时间:2011-05-19 05:38:54

标签: c pointers memory-management

考虑c代码:

void mycode() {
  MyType* p = malloc(sizeof(MyType));
  /* set the values for p and do some stuff with it */
  cleanup(p);
}


void cleanup(MyType* pointer) {
  free(pointer);
  pointer = NULL;
}

我错误地认为在调用cleanup(p);之后,p的内容现在应该是NULL吗? cleanup(MyType* pointer)会正确释放内存分配吗?

我正在编写我的大学作业,并发现调试器仍然显示指向内存地址而不是0x0(或NULL),如我所料。

我发现C中的内存管理非常复杂(我希望不仅仅是我)。能不能说明正在发生的事情?

6 个答案:

答案 0 :(得分:18)

是的,这将正确释放内存。

清理函数中的

pointer是局部变量;仅为该函数本地存储的值传递的副本。

这可能会增加您的困惑,但您可以从p方法调整变量mycode的值,如下所示:

void cleanup(MyType** pointer) {
  free(*pointer);
  *pointer = NULL;
}

在这种情况下,pointer存储指针的地址。通过解除引用,您可以更改存储在该地址的值。

我将注意到,在软件的同一逻辑“级别”处理分配和释放通常是一种好习惯 - 即不要让调用者负责分配内存然后将其释放到函数内部。保持一致并处于同一水平。

答案 1 :(得分:10)

cleanup将正确释放p,但不会更改其值。 C是一种按值传递的语言,因此您无法从被调用函数更改调用者的变量。如果您想从p设置cleanup,则需要执行以下操作:

void cleanup(MyType **pointer) {
  free(*pointer);
  *pointer = NULL;
}

并称之为:

cleanup(&p);

您的代码有点不恰当,您能解释一下为什么要编写这个cleanup函数吗?

答案 2 :(得分:7)

是: malloc(3)神奇地产生了一块内存。您已将此内存的地址(而非内存本身)以任何有意义的方式分配给pauto变量的指针mycode()

然后,您通过值将p传递给cleanup(),这将复制指针,并使用cleanup()本地副本释放该块。 cleanup()然后将它自己的指针实例设置为NULL,但这没用。函数完成后,参数pointer就不复存在了。

回到mycode(),您仍然有指针p持有一个地址,但该块现在位于空闲列表中,对于存储非常有用,直到再次分配。

你可能会注意到你甚至可以存储到*p,并从中回读,但是会发生各种下游丢失,因为这块内存现在属于库,你可能会损坏它的数据结构或者malloc()块的未来所有者的数据。

仔细阅读C可以给出一个关于变量生命周期的抽象概念,但是将参数传递和局部变量分配的近通用(对于编译语言,无论如何)的实现可视化为堆栈操作要容易得多。它有助于在C课程之前参加装配课程。

答案 3 :(得分:3)

这不起作用,因为pointer中的cleanup()是本地的,因此调用函数看不到它NULL。有两种常见的方法可以解决这个问题。

  1. 不是发送清理指针,而是向指针发送指针。因此,更改cleanup()如下:
  2. void cleanup(MyType** pointer)
    {
      free(*pointer);
      *pointer = NULL;
    }
    

    然后只需致电cleanup(&p)

    1. 第二个选项很常见,就是使用一个#define宏来释放内存并清理指针。
    2. 如果您使用的是C ++,那么第三种方法是将cleanup()定义为:

      void cleanup(MyType& *指针)   {      //你的旧代码保持不变   }

答案 4 :(得分:1)

这里有两个问题:

  

以后我想错了   清理(​​P);被称为,内容   p现在应该是NULL?

是的,这是错误的。在调用free之后,指针指向的内存被释放。这并不意味着指针指向的内容设置为NULL。此外,如果您希望指针pmycode中变为NULL,则不会发生这种情况,因为您将p copy 传递给cleanup }。如果您希望p中的mycode为NULL,则需要指向cleanup中指针的指针,即清除签名为cleanup(MyType**)

第二个问题:

  

将正确清理(MyType *指针)   释放内存分配?

是的,因为你在free返回的指针上执行malloc,内存将被释放。

答案 5 :(得分:1)

不只是你。

cleanup()将正确清理您的分配,但不会将指针设置为NULL(应该将IMHO视为与清除分开。)指针指向的数据通过指针传递给cleanup(),并且free()正确编辑,但指针本身按值传递,因此当您将其设置为NULL时你只影响cleanup()函数的指针本地副本,而不是原始指针。

有三种方法:

  1. 使用指向指针的指针。

    void cleanup(struct MyType **p) { free(*p); *p = NULL; }
    
  2. 使用宏。

    #define cleanup(p) do { free(p); p = NULL; } while(0)
    

    或(可能更好):

    void cleanup_func(struct MyType *p) { /* more complicated cleanup */ }
    #define cleanup(p) do { cleanup_func(p); p = NULL; } while(0)
    
  3. 负责将NULL指针设置给调用者。这可以避免不必要的分配和代码混乱或破坏。