我想知道是否可以使用结构中定义的方法释放结构。这是一个简单的演示代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct testmem {
int a;
void (*free)(void *);
} testmem;
void xfree(void *mem) {
testmem *tm = (testmem *)mem;
printf("Before: a = %d\n", tm->a);
free(mem);
printf("After: a = %d\n", tm->a);
}
int main(int argc, char* argv[]) {
testmem *tm = (testmem *)malloc(sizeof(testmem));
tm->free = xfree;
tm->a = 10;
(*tm->free)(tm);
return 0;
}
我使用gcc toy.c -o toy
编译代码,并产生以下结果
Before: a = 10
After: a = 0
我想知道我是否已成功释放分配的内存。
我的困惑是,当调用tm->free
释放tm
时,tm->free
也将被释放,tm->free
执行时会损坏吗?
答案 0 :(得分:4)
我的困惑是,当调用
tm->free
释放tm
时,tm->free
也将被释放,tm->free
执行时会损坏吗?
tm->free
并不是全部功能。它仅仅是一个指针。 xfree
函数的代码完全在任何testmem
对象占用的内存区域之外。
您还必须在此处记录事件的顺序。在执行函数主体中的任何操作之前,先评估tm->free
以获得xfree
的地址。因此,调用时指向该函数的指针有效。到目前为止,它仅是有效的。指针可以在函数执行期间失效,但不再重要,因为不再需要其值。
作为一个补充说明,并且出于某些额外的类型安全性,您无需弄乱void*
和指针转换。具有相同的功能...
typedef struct testmem {
int a;
void (*free)(struct testmem *);
} testmem;
void xfree(testmem *mem) {
printf("Before: a = %d\n", mem->a);
free(mem);
// Can't use mem anymore, it's invalid after free is called
}
...但是可以避免将不相关的指针类型传递给函数。
答案 1 :(得分:2)
您的代码是有效的(如其余回答所述),除了您在调用它的指针之后释放引用的那一行之外:
printf("After: a = %d\n", tm->a);
我的答案将集中于提出一种在将来识别程序中内存泄漏的方法。
我建议使用valgrind。它是一个功能强大的框架,其功能之一是对程序进行内存管理分析。实际上,它可以通知您程序中的内存泄漏。
有很多选项,但是可以通过简单的形式运行:
valgrind --leak-check=yes -v ./<your_exe_name>
运行以上命令:
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 2 allocs, 2 frees, 528 bytes allocated
All heap blocks were freed -- no leaks are possible
因此很明显,自由操作已成功执行,并且程序没有任何内存泄漏。
答案 2 :(得分:0)
正如@StoryTeller指出的那样,在调用free之后,您不应该取消对指针的引用。但是,是的,free(mem)将释放分配给tm的内存。
答案 3 :(得分:0)
该原理当然是有效的,并且在处理多态对象(可能表示不同含义的void *数据成员)时使用。