我有一个名为Grid的结构,它包含一个2d字符串数组。我一直在搜索如何正确释放多维数组,并且似乎无法通过此过程找到问题,因为valgrind一直在检测错误和泄漏内存。提前谢谢!
typedef struct Grid{
int N;
int M;
char ***adj;
}TGrid;
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i, j;
for(i = 0; i < Grid->N; i++){
for(j = 0; j < Grid->M; j++){
free(Grid->adj[i][j]);
}
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
答案 0 :(得分:2)
malloc
内存的方式不正确,应采取正确的方法:
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
return Grid;
}
请注意,Grid->adj[i][j]
始终指向10个字符的数组,您可以使用:
#include <stdio.h>
#include <stdlib.h>
typedef struct Grid{
int N;
int M;
char (**adj)[10];
}TGrid;
TGrid* emptyGrid(int N, int M){
int i;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char (*)[10]));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char[10]));
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i;
for(i = 0; i < Grid->N; i++){
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
int main() {
TGrid* t = emptyGrid(2,3);
freeGrid(t);
return 0;
}
但是,由于free
收到void*
参数,因此您的代码中必须包含其他内容。
答案 1 :(得分:2)
您的代码的一般结构很好,但sizeof
下的类型是错误的。 malloc
内存的一般习惯用法如下
T *p = malloc(N * sizeof *p);
或等同于
T *p = malloc(N * sizeof(T));
请注意,在后一种(基于类型的)变体中,sizeof
下的星号比收件人指针类型少一个星号。
确切地说,在你的情况下它应该如何
Grid->adj = malloc(N * sizeof(char **));
/* Since `Grid->adj` is `char ***`, you should have `char **` under `sizeof` */
...
Grid->adj[i] = malloc(M * sizeof(char *));
/* Since `Grid->adj[i]` is `char **`, you should have `char *` under `sizeof` */
...
Grid->adj[i][j] = malloc(10 * sizeof(char));
/* Since `Grid->adj[i][j]` is `char *`, you should have `char` under `sizeof` */
如果那不是您所需要的,那么您的类型肯定有问题。如果不知道你的意图,就没办法说。
(我建议您使用第一种方法在sizeof
下指定malloc
- 使用表达式,而不是类型。这样您就不必计算星号。)
但是,在现实生活中,这种特定错误通常只会导致过度分配的内存。不应发生越界访问或内存泄漏。如果valgrind报告此类错误,那么此处也必须有其他工作。
答案 2 :(得分:1)
由于您尚未发布使用这些功能的代码,因此很难确定问题所在。
我想指出需要更改对malloc
的调用。
你有:
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
这些电话需要更改为:
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
您可以使用以下编码样式来避免此类错误:
Grid->adj = malloc(N * sizeof(*(Grid->adj)));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(*(Grid->adj[i])));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(*(Grid->adj[i][j])));
}
}
使用相同样式的简单案例:
char* cp = malloc(10*sizeof(*cp));
答案 3 :(得分:1)
您没有分配数组,而是分配基于指针的查找表。这样做的唯一原因是,如果您希望各个尺寸具有不同的长度(例如在字符串数组中)。如果你不需要它,你就不应该使用指针到指针表,因为它们很慢,容易出错并且不必要地复杂。
要分配实际的3D数组,您可以这样做:
char (*array)[Y][Z] = malloc ( sizeof(char[X][Y][Z] );
...
free(array);
要分配字符串数组,您可以这样做:
char** lookup = malloc ( sizeof( char*[N] ) );
for(size_t i=0; i<N; i++)
{
lookup[i] = ...; // assign pointers to strings
}
...
free(lookup);
根据经验,只要程序包含两个以上的间接级别,程序设计就很可能很糟糕。