如果我在C中有几个链接结构:
struct structA {
int a;
int b;
struct structA *next;
}
struct structB {
char a;
int b;
struct structB *next;
}
我动态分配内存如下:
struct structA *mystructA = (struct structA*) malloc(sizeof(struct structA));
mystructA->next = (struct structA*) malloc(sizeof(struct structA));
struct structB *mystructB = (struct structB*) malloc(sizeof(struct structB));
mystructB->next = (struct structB*) malloc(sizeof(struct structB));
我是否总是必须为每个结构类型释放它,如下所示:
struct structA *p, *pNext;
for (p = mystructA; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
struct structB *p, *pNext;
for (p = mystructB; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
或者有没有通用的解决方案?我假设没有其他解决方案,因为free()
过程必须知道必须释放多少字节。但也许我错了,有人可以教我更好。
答案 0 :(得分:5)
标准方法是使“list part”成为结构的第一个元素,并让每个派生的结构共享同一个前缀。由于保证第一个元素位于零偏移处,因此这将起作用。 示例摘录:
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
};
struct structA {
struct list list;
int a;
int b;
};
struct structB {
struct list list;
char a;
int b;
};
void *create_any(size_t size)
{
struct list *this;
this = malloc (size);
if (!this) return this;
memset(this, 0, size);
this->next = NULL;
return this;
}
void free_all_any(struct list **lp) {
struct list *tmp;
while ((tmp = *lp)) { *lp = tmp->next; free(tmp); }
}
#define CREATE_A() create_any(sizeof(struct structA))
#define CREATE_B() create_any(sizeof(struct structB))
#define FREE_A(pp) free_any((struct list **) pp)
#define FREE_B(pp) free_any((struct list **) pp)
int main(void)
{
struct structA *ap;
struct structB *bp;
ap = CREATE_A ();
bp = CREATE_B ();
// some code here ...
FREE_A( &ap);
FREE_B( &bp);
return 0;
}
这或多或少是linux内核中使用的方法,但在那里使用了更多的预处理器魔法。 (显然没有malloc)
答案 1 :(得分:2)
由于free()
接受指向void *
的指针,而structA
和structB
都具有相同的大小,因此您可以传递两种指针类型。
为什么你有两个具有相同成员的不同结构?
为什么没有通用列表项类型,例如:
struct list_node {
void *data;
struct list_node *next;
}
答案 2 :(得分:2)
实际上,这是一个非常有趣的问题。这部分是正确的,您必须单独free()
每个struct
类型,因为它们已经malloc()
单独编辑,并且每个内存块都已专门为该类型分配。此外,在某些系统char
和int
具有不同的存储大小,但您可以尝试使用Phillip提供的解决方案。有关详细信息,请参阅doom memory engine。在旁注,please don't cast malloc()
in C。有趣的是,一旦程序终止,操作系统将回收内存,所以如果你只是在程序结束时解除分配结构,当你不再需要它们时,可能没有必要{{{ 1}}他们