何时在C语言中为结构体和“创建”函数分配内存?

3
考虑一个结构体,比如List,并且有一个返回新List的函数叫做ListCreate()。ListCreate()接受一个对象指针作为参数,这是List的属性。
据我的理解,分配堆内存应该由调用者处理。
最初,我的ListCreate()为将要返回的新List对象分配了内存,并返回了指向该List对象的指针。这似乎没有引起任何问题,但现在我意识到让调用者处理这个任务更合理。
然而,令我困惑的是,如果我像下面这样创建一个List对象:
List* ListCreate(*foo fum) {
    struct List ls;
    ls.foo = fum;
    ls.data = 0;

    return &ls;
}

如果我将List(ls.foo)的属性传回到在main()中为List对象分配了自己内存的List指针,那么ls.foo、ls.data(以及其他可能的属性)和&ls只存在于此函数的本地环境中,不再有意义。

我正在考虑的一个解决方案是让ListCreate()在堆上为List对象的属性分配内存,然后由其相应的ListDestroy()函数来处理释放该内存,但我认为这意味着List对象的所有属性实际上都应该是指向它们所指向的任何内容的指针。

我不知道这是否是常规做法——如果我的理解是正确的,那么这种情况通常如何处理?


2
我看到你提到的动态分配是在Create/Destroy上下文中,这种情况通常出现在调用者不知道结构体实现的情况下 - 例如前向声明,调用者无法实例化不完整类型。 - polarysekt
2个回答

1

始终创建平行的createdestroy函数(即使destroy只是对free的调用),并且通常避免直接访问其成员的函数(如果可能,将其设置为不透明)。

List *ListCreate(Foo *arg) { List *rv = calloc(1, sizeof(List)); rv.arg = arg; return rv; }
void ListDestroy(List *lst) { free(lst); }

0
你所建议的解决方案是常规方式。 在调用函数中执行以下操作:
struct List ls;

然后在被调用的函数中:

int ListCreate(*foo fum, struct List *ls) {

    ls->foo = fum;
    ls->data = 0;

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接