如果我有一个结构:
struct Cell
{
unsigned int *x, *y;
char flag;
};
以下构造函数和解构器是否足以安全地分配和取消分配内存?
// Constructor function.
struct Cell *Cell_new()
{
struct Cell *born = malloc(sizeof(struct Cell));
if (born == NULL)
return NULL;
born->x = NULL;
born->y = NULL;
born->flag = false;
return born;
}
// Deconstructor function.
// When called, use Cell_destroy(&cell);
char Cell_destroy(struct Cell **cell)
{
free(cell);
cell = NULL;
}
这是对的吗?
我不明白的一件事是,如果我这样做:
struct Cell *myCell = Cell_new();
Cell_destroy(&myCell);
当我正在调用destroy
时,它期望一个地址指向一个指针(一个指向指针的指针),但我还是为一个结构提供了一个地址。
我的意思是
我的功能期望:
Pointer -> Pointer -> Tangible Object
我给予的是什么:
Pointer -> Tangible Object
这是有缺陷的逻辑吗?我已经查了一段时间了,所以可以说我可能会让自己感到困惑。
答案 0 :(得分:5)
将类型struct Cell **
的参数传递给析构函数是正确的,因为此函数将更改指针的值。
因此,如果要释放对象并将指针设置为NULL,则可以编写:
void Cell_destroy(struct Cell **cell)
{
free(*cell);
*cell = NULL;
}
请注意cell
如何被取消引用。
答案 1 :(得分:1)
我会考虑结构中x
和y
指针指向的内存。如果这些指针非空,那么代码的哪一部分负责(“拥有”)该内存?一个典型的做法是在Cell_destroy
中检查null,如果x或y为非null,则在它们上面调用free
,如果是你的Cell ADT的其他部分的情况(抽象数据类型)通过malloc
动态分配该内存。可以肯定的是,free(cell)
只释放结构本身使用的内存,而不释放x
和y
指向的任何内存。
关于Cell_destroy
获取指向指针的指针,因此可以将传入的指针设置为null,这是析构函数工作的一种非典型方式...... {{1}本身的工作更典型 - 将传入的指针归零通常是free
调用者留下的工作。
答案 2 :(得分:1)
代码需要释放它分配的相同指针。释放取消引用的值。
代码也缺少返回值。建议只使用void
函数。
代码还应该释放字段的指针x
和y
。
代码应该容忍使用相同指针和空指针的重复调用。添加if (*cell)
void Cell_destroy(struct Cell **cell) {
if (*cell) {
free((*cell)->x);
free((*cell)->y);
free(*cell);
*cell = NULL;
}
}
答案 3 :(得分:0)
不,这不正确。
destroy函数不应该返回char。它应该有返回类型void。
此外,该函数应该使用指针而不是双指针,并且不应将单元格设置为null。在调用destroy时不要接受myCell的地址。