gpt4 book ai didi

c - 如何分配/释放包含二维数组的结构

转载 作者:太空宇宙 更新时间:2023-11-04 05:49:24 25 4
gpt4 key购买 nike

所以我的目标是分配一个包含二维数组的迷宫结构;但是,当我尝试为二维数组的每个“单元格”分配内存时,之后似乎无法正确释放它。有没有一种方法可以在一行中 malloc 结构,或者至少可以通过 free_maze 函数轻松释放分配的内存?我附上了我的 .c 文件以及定义结构的头文件。此外,我附上了一个包含在文本文件中的迷宫示例。

#include <stdlib.h>
#include "maze.h"


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){
free(maze);
}

Maze* read_maze(FILE* fp){
Maze* maze;
char c = fgetc(fp);
int rows = 0;
int cols = 0;
int chars = 0;
while(c != EOF){
chars++;
c = fgetc(fp);
}
rewind(fp);
while(c != '\n'){
cols++;
c = fgetc(fp);
}
rows = chars / cols;
cols--;
maze = malloc_maze(rows, cols);
rewind(fp);
for(int row_count =0; row_count <= rows; row_count++){
for(int col_count = 0; col_count < cols; col_count++){
fseek(fp, (row_count*(cols+1)+col_count), SEEK_SET);
maze -> cells[col_count][row_count] = fgetc(fp);
}
}
maze -> num_rows = rows;
maze -> num_cols = cols;
return maze;
}

bool write_maze(const char* filename, const Maze* maze){
FILE* ha;
ha = fopen(filename, "w");
if(ha == NULL){
return false;
}
rewind(ha);
int rows = maze -> num_rows;
int cols = maze -> num_cols;
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
fputc(maze -> cells[j][i], ha);
}
fputc('\n', ha);
}
fclose(ha);
return true;
}

/////////////////header file//////////////////////////

#ifndef MAZE_H
#define MAZE_H

#define WALL 'X'
#define PATH ' '

#include <stdio.h>
#include <stdbool.h>

typedef struct _Maze {
int num_rows;
int num_cols;
char** cells;
} Maze;

Maze* malloc_maze(int num_rows, int num_cols);

void free_maze(Maze* maze){
__attribute__((nonnull));
}

Maze* read_maze(FILE* fp){
__attribute__((nonnull));
}

bool write_maze(const char* filename, const Maze* maze){
__attribute__((nonnull));
}

///////////////example maze within .txt file/////////////////////


XXXXX XXX
X X
X XXX XXX
X X X X
X X XXXXX
X X
XXXXX XXX

最佳答案

给定一个分配器函数,释放器会自行编写 - 您可以按照与分配指针大致相反的顺序释放指针。

因此,假设分配器是(仅根据问题重新格式化——功能不变):

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);
}

这确保代码在释放内存后不会尝试访问内存。


然而,对分配器的更仔 segmentation 析表明存在一些(小)问题。例如,通常您将这对索引视为 maze->cells[row][col],但内存分配要求将其用作 maze->cells[col][行]。两者都可以工作,但行列顺序在 C 中更常见。另外,第二个和第三个 malloc() 调用中的大小不正确。对你来说幸运的是,第二个以 sizeof(char **) 为单位分配而不是 sizeof(char *),但它们的大小相同,所以它“doesn没关系”。第三个分配 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;
}

这会在分配失败时清理部分分配的内存。它不会更改释放代码(除非你想添加空检查,但如果分配失败,你不应该调用释放代码)。

关于c - 如何分配/释放包含二维数组的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47746099/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com