2

如果我在 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()过程必须知道必须释放多少字节。但也许我错了,有人可以教我更好。

4

3 回答 3

5

标准方法是让“列表部分”成为结构的第一个元素,并让每个派生结构共享相同的前缀。由于保证第一个元素放置在偏移量零处,这将起作用。示例片段:

#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)

于 2013-07-19T13:31:14.837 回答
2

由于free()接受指向void *and的指针,structA并且structB两者具有相同的大小,因此您可以传递两种指针类型。

然而,这在优雅方面并不是最佳的。你应该思考以下问题:

为什么你有两个具有相同成员的不同结构?

为什么没有通用列表项类型,例如以下:

struct list_node {
    void *data;
    struct list_node *next;
}
于 2013-07-19T13:01:32.393 回答
2

实际上,这是一个非常有趣的问题。这部分是正确的,您必须单独使用free()每种struct类型,因为它们已经malloc()单独 -ed,并且每个内存块都已专门为该类型分配。此外,在某些系统上char并且int具有不同的存储大小,但您可以尝试类似的解决方案菲利普提供。欲了解更多信息,请阅读末日内存引擎。附带说明,请不要malloc()在 C 中强制转换。有趣的是,一旦程序终止,操作系统会回收内存,所以如果你只在程序接近结束时释放结构,当你不再需要它们时,可能就不需要它们free()

于 2013-07-19T13:07:08.680 回答