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

Ash*_*Ash 10 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;
}
Run Code Online (Sandbox Code Playgroud)

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

我正在编写我的大学作业,并发现调试器仍然显示指针有一个内存地址而不是0x0(或NULL),正如我所期望的那样.

我发现C中的内存管理非常复杂(我希望不仅仅是我).任何人都可以了解正在发生的事情吗?

sje*_*397 18

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

pointer清理函数里面是一个局部变量; 仅为该函数本地存储的值的副本.

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

void cleanup(MyType** pointer) {
  free(*pointer);
  *pointer = NULL;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 您错过了,这里的调用需要是“cleanup(&p);” (2认同)

Car*_*rum 11

cleanup将适当释放p,但不会改变其价值.C是一种按值传递的语言,因此您无法从被调用函数更改调用者的变量.如果你想设置pcleanup,你需要做的是这样的:

void cleanup(MyType **pointer) {
  free(*pointer);
  *pointer = NULL;
}
Run Code Online (Sandbox Code Playgroud)

称之为:

cleanup(&p);
Run Code Online (Sandbox Code Playgroud)

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


Dig*_*oss 7

是的:malloc(3) 神奇地产生了一块记忆.你已经将这个内存的地址,但没有以任何有意义的方式将内存本身分配给p作为auto变量的指针mycode().

然后,你传递pcleanup(),由值,这将复制指针,使用复制本地cleanup(),释放块.cleanup()然后将它自己的指针实例设置为NULL,但这没用.一旦功能完成,参数pointer就不再存在.

回到mycode(),你仍然有指针p保存一个地址,但该块现在在空闲列表中,并且在再次分配之前对存储没有特别有用.

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

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