从 C 中其他函数内部释放指针
考虑一下 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 中的内存管理非常复杂(我希望不仅仅是我)。任何人都可以阐明正在发生的事情吗?
Consider the c code:
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;
}
Am I wrong in thinking that after cleanup(p);
is called, the contents of p should now be NULL? Will cleanup(MyType* pointer)
properly free the memory allocation?
I am coding my college assignment and finding that the debugger is still showing the pointer to have a memory address instead of 0x0 (or NULL) as I expect.
I am finding the memory management in C to be very complicated (I hope that's not just me). can any shed some light onto what's happening?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,这将正确释放内存。
cleanup函数内部的
pointer
是一个局部变量;仅为该函数在本地存储的传入值的副本。这可能会增加您的困惑,但您可以从
cleanup
内部调整变量p
的值(对于mycode
方法来说是本地的) > 方法如下:在这种情况下,
pointer
存储指针的地址。通过取消引用,您可以更改存储在该地址的值。您将像这样调用cleanup
方法:(也就是说,您想要传递指针的地址,而不是其值的副本。)
我会注意到,处理这种情况通常是很好的做法在软件的同一逻辑“级别”上进行分配和释放 - 即不要让调用者负责分配内存,然后在函数内释放它。保持一致并处于同一水平。
Yes that will free the memory correctly.
pointer
inside the cleanup function is a local variable; a copy of the value passed in stored locally for just that function.This might add to your confusion, but you can adjust the value of the variable
p
(which is local to themycode
method) from inside thecleanup
method like so:In this case,
pointer
stores the address of the pointer. By dereferencing that, you can change the value stored at that address. And you would call thecleanup
method like so:(That is, you want to pass the address of the pointer, not a copy of its value.)
I will note that it is usually good practice to deal with allocation and deallocation on the same logical 'level' of the software - i.e. don't make it the callers responsibility to allocate memory and then free it inside functions. Keep it consistent and on the same level.
cleanup
将正确释放p
,但不会更改其值。 C 是一种按值传递语言,因此您无法从被调用函数更改调用者的变量。如果您想从cleanup
设置p
,您需要执行以下操作:并这样称呼它:
您的代码有点不惯用,您能解释一下吗更好一点为什么要编写这个
cleanup
函数?cleanup
will properly freep
, but it won't change its value. C is a pass-by-value language, so you can't change the caller's variable from the called function. If you want to setp
fromcleanup
, you'll need to do something like:And call it like:
Your code is a little bit un-idiomatic, can you explain a bit better why you want to write this
cleanup
function?是
是
是:有一块内存是由
malloc
(3)神奇地产生的。您已将此内存的地址(但不是内存本身)以任何有意义的方式分配给指针p
,该指针是mycode()< 中的
auto
变量/代码>。然后,按值将
p
传递给cleanup()
,这将复制指针,并使用cleanup()
的本地副本,释放该块。cleanup()
然后将它自己的指针实例设置为 NULL,但这没有用。一旦函数完成,参数指针就不再存在。回到
mycode()
,您仍然有指针p
保存地址,但是该块现在位于空闲列表上,并且在再次分配之前对于存储并不是很有用。您可能会注意到,您甚至仍然可以存储到
*p,
并从中读回,但是会发生各种数量的下游损失,因为该内存块现在属于库,并且您可能会损坏其数据结构或 malloc() 块的未来所有者的数据。仔细阅读 C 语言可以让您对变量生存期有一个抽象的概念,但是将参数传递和局部变量分配的近乎通用(无论如何对于编译语言)实现可视化为堆栈操作要容易得多。在 C 课程之前学习汇编课程会有所帮助。
Yes
Yes
Yes: There is a block of memory magically produced by
malloc
(3). You have assigned the address of this memory, but not the memory itself in any meaningful way, to the pointerp
which is anauto
variable inmycode()
.Then, you pass
p
tocleanup()
, by value, which will copy the pointer and, using the copy local tocleanup()
, free the block.cleanup()
then sets it's own instance of the pointer to NULL, but this is useless. Once the function is complete the parameterpointer
ceases to exist.Back in
mycode()
, you still have pointerp
holding an address, but the block is now on the free list and not terribly useful for storage until allocated again.You may notice that you can even still store to and read back from
*p,
but various amounts of downstream lossage will occur, as this block of memory now belongs to the library and you may corrupt its data structures or the data of a future owner of a malloc() block.Carefully reading about C can give you an abstract idea of variable lifetime, but it's far easier to visualize the near-universal (for compiled languages, anyway) implementation of parameter passing and local variable allocation as stack operations. It helps to take an assembly course before the C course.
这不起作用,因为
cleanup()
中的指针
是本地的,因此调用函数看不到为其分配NULL
。有两种常见的方法可以解决这个问题。cleanup()
更改如下:然后只需调用
cleanup(&p)
。如果您使用 C++,则还有第三种方法,将 cleanup() 定义为:
void cleanup(MyType& *pointer)
{
// 你的旧代码保持不变
}
This won't work as the
pointer
incleanup()
is local, and thus assigning itNULL
is not seen by the calling function. There are two common ways of solving this.cleanup()
as follows:and then just call
cleanup(&p)
.#define
macro that frees the memory and cleans the pointer.If you are using C++ then there is a third way by defining
cleanup()
as:void cleanup(MyType& *pointer)
{
// your old code stays the same
}
这里有两个问题:
是的,这是错误的。调用
free
后,指针指向的内存被释放。这并不意味着指针指向的内容被设置为 NULL。另外,如果您期望指针p
在mycode
中变为 NULL,则不会发生这种情况,因为您正在传递p 的副本
到清理
。如果您希望mycode
中的p
为 NULL,那么您需要一个指向cleanup
中的指针,即 cleanup 签名将为清理(MyType**)
。第二个问题:
是的,由于您正在对
malloc
返回的指针执行free
操作,因此内存将被释放。There are two questions are here:
Yes, this is wrong. After calling
free
the memory pointed by the pointer is deallocated. That doesn't mean that the content pointed by the pointer is set to NULL. Also, if you are expecting the pointerp
to become NULL inmycode
it doesn't happen because you are passing copy ofp
tocleanup
. If you wantp
to be NULL inmycode
, then you need a pointer to pointer incleanup
, i.e. the cleanup signature would becleanup(MyType**)
.Second question:
Yes, since you are doing
free
on a pointer returned bymalloc
the memory will be freed.不只是你。
cleanup()
将正确清理您的分配,但不会将指针设置为NULL
(恕我直言,这应该被视为与清理分开。)数据指向的指针通过指针传递给cleanup()
,并正确地free()
,但指针本身按值传递,因此当您将其设置为 NULL 时您只会影响cleanup()
函数的指针的本地副本,而不是原始指针。有三种方法可以解决这个问题:
使用指向指针的指针。
使用宏。
或者(可能更好):
将设置指向
NULL
的指针的责任留给调用者。这可以避免不必要的赋值以及代码混乱或损坏。It's not just you.
cleanup()
will properly clean up your allocation, but will not set the pointer toNULL
(which should IMHO be regarded as separate from cleanup.) The data the pointer points to is passed tocleanup()
by pointer, and isfree()
ed properly, but the pointer itself is passed by value, so when you set it toNULL
you're only affecting thecleanup()
function's local copy of the pointer, not the original pointer.There are three ways around this:
Use a pointer to a pointer.
Use a macro.
or (probably better):
Leave the responsibility of setting pointers to
NULL
to the caller. This can avoid unnecessary assignments and code clutter or breakage.