假设我有一个函数,它分配一些结构(对象),并且在设置其字段时必须分配额外的数据。由于每次分配都可能失败,因此对象创建可能只能部分成功。清理这个混乱的最常见方法是什么?我想最直接的事情是这样的:
struct Obj {
struct ChildObj1 *child_obj1;
struct ChildObj2 *child_obj2;
};
struct Obj *obj_create()
{
struct Obj *obj = malloc(sizeof(struct Obj));
if (!obj) {
return NULL;
}
obj->child_obj1 = child_obj1_create();
if (!obj->child_obj1) {
free(obj);
return NULL;
}
obj->child_obj2 = child_obj2_create();
if (!obj->child_obj2) {
free(obj->child_obj1);
free(obj);
return NULL;
}
return obj;
}
我觉得如果要创建很多对象,这可能会变得非常乏味。另外,当您稍后进行更改时,您可能很容易忘记更新“免费放松”。我正在考虑的另一种选择是利用我需要的“析构函数”,但要确保对结构进行零初始化。像这样:
struct Obj *obj_create()
{
struct Obj *obj = malloc(sizeof(struct Obj));
memset(obj, 0, sizeof(struct Obj));
if (!obj) {
return NULL;
}
obj->child_obj1 = child_obj1_create();
if (!obj->child_obj1) {
obj_destroy(obj);
return NULL;
}
obj->child_obj2 = child_obj2_create();
if (!obj->child_obj2) {
obj_destroy(obj);
return NULL;
}
return obj;
}
void obj_destroy(struct Obj *obj)
{
if (!obj)
return;
if (obj->child_obj2)
free(obj->child_obj2);
if (obj->child_obj1)
free(obj->child_obj1);
free(obj);
}
这种做法有什么问题吗?还有其他更好的选择吗?
使用类似析构函数的函数接收指向对象的指针,释放可能与其相关的所有内容(如果已分配),最后释放对象本身。你也可以这样做:
if (
(!(obj->child_obj1 = child_obj1_create())) ||
(!(obj->child_obj2 = child_obj2_create()))
) {
obj_destroy(obj);
return NULL;
}
return obj;