C malloc释放结构时出错

C malloc释放结构时出错,c,memory-management,struct,malloc,free,C,Memory Management,Struct,Malloc,Free,我刚刚重新开始学习C,但我对一些内存管理细节感到困惑。 我要走了 未分配正在释放的指针。。。流产陷阱 对于下面的代码。我真的每个malloc需要1个免费的吗?为什么我的代码错了? 谢谢 #define N 9 typedef struct { int MAX_LIST_SIZE; int length; int *ini; }List; /* allocates new List and its data */ List *newList(int size) { List

我刚刚重新开始学习C,但我对一些内存管理细节感到困惑。 我要走了

未分配正在释放的指针。。。流产陷阱

对于下面的代码。我真的每个malloc需要1个免费的吗?为什么我的代码错了?
谢谢

#define N 9

typedef struct
{
  int MAX_LIST_SIZE;
  int length;
  int *ini;
}List;

/* allocates new List and its data */
List *newList(int size)
{
    List *list = malloc(sizeof(List));
    list->MAX_LIST_SIZE = size;
    list->length = 0;
    list->ini = malloc(sizeof(int) * size);

    return list;
}

/* add some value to the list */
void addList(List *list, int val)
{
    if (list->length < list->MAX_LIST_SIZE)
        list->ini[list->length++] = val;
    else
        fprintf(stderr, "Error: add(): List is full.\n");
}

/* get an array of N*N lists malloc-ed Lists */
List *gridList()
{
    int i, j;
    List *cells = malloc(sizeof(List) * N * N);

    for (i = 0; i < N * N; i++)
    {
      /* malloc is called inside NewList()*/
      cells[i] = *newList(N);
      for (j = 0; j < N; j++)
          addList(&cells[i], j + 1);
    }

    return cells;
}


/* inside main */
List *cells = gridList();

/* use cells ... */

/* free */
for (i = 0; i < N * N;  i++)
{
    free(cells[i].ini);
    /* line below causes CRASH */
    free(&cells[i]);
}
#定义N 9
类型定义结构
{
int最大列表大小;
整数长度;
int*ini;
}名单;
/*分配新列表及其数据*/
列表*新列表(整数大小)
{
List*List=malloc(sizeof(List));
列表->最大列表大小=大小;
列表->长度=0;
列表->ini=malloc(sizeof(int)*大小);
退货清单;
}
/*在列表中添加一些值*/
无效地址列表(列表*列表,int val)
{
如果(列表->长度<列表->最大列表大小)
列表->ini[列表->长度++]=val;
其他的
fprintf(stderr,“错误:add():列表已满。\n”);
}
/*获取N*N个列表的数组malloc-ed列表*/
List*gridList()
{
int i,j;
列表*单元格=malloc(sizeof(列表)*N*N);
对于(i=0;i
问题是您正在分配一个列表数组,将列表的全部内容复制到数组元素中,然后尝试释放它们。最初分配的列表记录是内存泄漏,而空闲调用实际上是试图释放未malloc'ed(或者更确切地说是在单个大块中malloc'ed)的内存

您需要指向指针的指针数组来保存列表:

/* get an array of N*N lists malloc-ed Lists */
List **gridList()
{
    int i, j;
    // VV note change here
    List **cells = malloc(sizeof(List*) * N * N); 

    for (i = 0; i < N * N; i++)
    {
        /* malloc is called inside NewList()*/
        cells[i] = newList(N); // << Note change here.
        for (j = 0; j < N; j++)
            addList(cells[i], j + 1);
    }
    return cells;
}

/* free */
for (i = 0; i < N * N;  i++)
{
    free(cells[i]->ini); // << and here
    /* line below causes CRASH */
    free(cells[i]); // << and here
}
free(cells);
/*获取N*N个列表的数组malloc-ed列表*/
列表**gridList()
{
int i,j;
//这里有零钱
列表**单元格=malloc(sizeof(List*)*N*N);
对于(i=0;icells[i]=newList(N);///ini);//问题是您正在分配一个列表数组,将列表的完整内容复制到数组元素中,然后尝试释放它们。原始分配的列表记录是内存泄漏,而空闲调用确实在尝试释放未被malloc'ed的内存(或者更确切地说,是在一个大的街区里)

您需要指向指针的指针数组来保存列表:

/* get an array of N*N lists malloc-ed Lists */
List **gridList()
{
    int i, j;
    // VV note change here
    List **cells = malloc(sizeof(List*) * N * N); 

    for (i = 0; i < N * N; i++)
    {
        /* malloc is called inside NewList()*/
        cells[i] = newList(N); // << Note change here.
        for (j = 0; j < N; j++)
            addList(cells[i], j + 1);
    }
    return cells;
}

/* free */
for (i = 0; i < N * N;  i++)
{
    free(cells[i]->ini); // << and here
    /* line below causes CRASH */
    free(cells[i]); // << and here
}
free(cells);
/*获取N*N个列表的数组malloc-ed列表*/
列表**gridList()
{
int i,j;
//这里有零钱
列表**单元格=malloc(sizeof(List*)*N*N);
对于(i=0;i
cells[i] = *newList(N);
它将
单元格
中的每个元素设置为
新列表
动态分配的列表的副本。因此
新列表
动态分配一个列表,然后您将指针指向该动态分配的
列表
,取消引用它,并将其复制到
单元格[i]
。因此,稍后当您转到
free()
每个元素:

free(&cells[i]);
它不起作用,因为
单元格[i]
中的每个元素都是
列表,而不是
malloc()
分配的
列表*
(列表指针)

所以你有两个选择。一个(坏的选择)是删除最后一行
free()
,因为没有任何东西可以释放。然而,这只是掩盖了一个更大的问题,即你现在有内存泄漏,因为你不能返回并释放用
newList()
创建的动态分配的
列表

相反,您可能希望有一个指向列表的指针数组,您可以将其更改为:

List **cells = malloc(sizeof(List*) * N * N);
因此,
cells[i]
引用了一个
List*
newList()
返回这样一个指针,所以您可以将该行更改为:

cells[i] = newList(N);
addList(cells[i], j + 1);
类似地,
addList()
采用这样一个指针,因此您只需将该行更改为:

cells[i] = newList(N);
addList(cells[i], j + 1);
因为
&cells[i]
会将指针的地址传递给它,这不是您想要的

最后,将自由语句更改为:

free(cells[i]->ini); // ->init because cells[i] is now a pointer to a List, List *
free(cells[i]);
你可以:

cells[i] = *newList(N);
它将
单元格
中的每个元素设置为
新列表
动态分配的列表的副本。因此
新列表
动态分配一个列表,然后您将指针指向该动态分配的
列表
,取消引用它,并将其复制到
单元格[i]
。因此,稍后当您转到
free()
每个元素:

free(&cells[i]);
它不起作用,因为
单元格[i]
中的每个元素都是
列表,而不是
malloc()
分配的
列表*
(列表指针)

所以你有两个选择。一个(坏的选择)是删除最后一行
free()
,因为没有任何东西可以释放。然而,这只是掩盖了一个更大的问题,即你现在有内存泄漏,因为你不能返回并释放用
newList()
创建的动态分配的
列表

相反,您可能希望有一个指向列表的指针数组,您可以将其更改为:

List **cells = malloc(sizeof(List*) * N * N);
因此,
cells[i]
引用了一个
List*
newList()
返回这样一个指针,所以您可以将该行更改为:

cells[i] = newList(N);
addList(cells[i], j + 1);
类似地,
addList()
采用这样一个指针,因此您只需将该行更改为:

cells[i] = newList(N);
addList(cells[i], j + 1);
因为
&cells[i]
会将指针的地址传递给它,这不是您想要的

最后,将自由语句更改为:

free(cells[i]->ini); // ->init because cells[i] is now a pointer to a List, List *
free(cells[i]);

1) 代码不需要是“完整的”?2)3)我知道Java.C是一种很好的语言。但是@Beta关于小的、完整的、可编译的例子的观点非常好。如果你听从他的建议,你更有可能得到答案。@Beta:第1点和第2点非常好。至于第3点,这不是语言战争的地方。正如我所说的,代码是微不足道的对于一个“C类人”,这就是为什么我没有两者兼而有之