C结构自我释放

时间:2018-09-06 07:40:05

标签: c

我想知道是否可以使用结构中定义的方法释放结构。这是一个简单的演示代码:

#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执行时会损坏吗?

4 个答案:

答案 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 *数据成员)时使用。