给定一个分配器函数,释放器会自行写入 - 您按照与分配指针大致相反的顺序释放指针。
因此,鉴于分配器是(仅从问题重新格式化 - 功能不变):
Maze *malloc_maze(int num_rows, int num_cols)
{
Maze *maze = malloc(sizeof(*maze));
if (maze == NULL)
{
free(maze);
return NULL;
}
maze->cells = malloc(sizeof(maze->cells) * (num_cols));
if (maze->cells == NULL)
{
free(maze);
return NULL;
}
for (int i = 0; i < num_cols; i++)
{
maze->cells[i] = malloc(sizeof(*(maze->cells)) * (num_rows));
}
maze->num_rows = num_rows;
maze->num_cols = num_cols;
return maze;
}
释放器应该是:
void free_maze(Maze *maze)
{
for (int i = 0; i < num_cols; i++)
free(maze->cells[i]);
free(maze->cells);
free(maze);
}
这可确保代码在释放内存后不会尝试访问内存。
但是,对分配器的仔细分析表明存在一些(小)问题。例如,通常您将索引对视为maze->cells[row][col],但内存分配要求将其用作maze->cells[col][row]。两者都可以工作,但行列顺序在 C 中更常见。此外,第二个和第三个 malloc() 调用中的大小不正确。幸运的是,第二个以sizeof(char **) 而不是sizeof(char *) 为单位分配,但它们的大小相同,所以“没关系”。第三个分配sizeof(char *)单位,而不是sizeof(char),因此分配的内存比内存多得多(通常sizeof(char *)是4或8个字节,但sizeof(char)定义为1)。
因此,您最好使用它,它保留maze->cells[col][row] 访问符号:
Maze *malloc_maze(int num_rows, int num_cols)
{
Maze *maze = malloc(sizeof(*maze));
if (maze == NULL)
return NULL;
maze->cells = malloc(sizeof(maze->cells[0]) * num_cols);
if (maze->cells == NULL)
{
free(maze);
return NULL;
}
for (int i = 0; i < num_cols; i++)
{
maze->cells[i] = malloc(sizeof(maze->cells[0][0]) * num_rows);
if (maze->cells[i] == 0)
{
for (int j = 0; j < i; j++)
free(maze->cells[j]);
free(maze->cells);
free(maze);
return NULL;
}
}
maze->num_rows = num_rows;
maze->num_cols = num_cols;
return maze;
}
这会在分配失败时清理部分分配的内存。它不会改变释放代码(除非你想添加一个空检查,但如果分配失败,你不应该调用释放代码)。