问题创建和释放C动态阵列



我正在编写一个C程序,其中涉及在更改大小和条目之间传递2D数组。我决定将动态阵列与指针一起使用。

每当我将指针释放到数组中时,我都会发现我擦除了其他阵列中的值。我可以成功更改指针指向的数组。我相信这是我释放指针或宣布指示的方式的问题。以下是我用来创建和免费指针到我的数组的代码。

int** create_array(int m, int n)
{
  int i;
  int* values = calloc(m * n, sizeof(int));
  int** rows = malloc(n * sizeof(int*));
  for(i = 0; i < n; i++) {
    rows[i] = values + (i * m);
  }
  return rows;
}
void destroy_array(int** arr)
{
  free(arr[0]);
  free(arr);
}

旧代码要创建和免费指针

int** create_array(int m, int n)
{
  int i;
  int* values = calloc(m * n, sizeof(int));
  int** rows = malloc(n * sizeof(int*));
  for(i = 0; i < n; i++) {
    rows[i] = values + (i * m * sizeof(int));
  }
  return rows;
}
void destroy_array(int** arr, int m, int n)
{
  int i;
  for(i = 0; i < n; i++) {
    free(arr[i]);
  }
  free(arr);
}

我的程序将指针销毁到一个数组后,然后尝试从另一个数组中读取值。以下是我将指针销毁这些阵列的代码。位置_last和位置都是我可以在此之前正确阅读的数组。

positions_last = positions;
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
fflush(stdout); // this prints fine
destroy_array(positions);
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
fflush(stdout); // this does not print, I get a segfault at this point

我刚刚进行了一个基本测试,这表明该问题在于我当前的代码来创建或破坏数组(据我所知)。

int** positions2 = create_array(10, 3);
int** positions3 = create_array(10, 3);
printf("%d %d %d", positions3[0][1], positions3[1][1], positions3[2][1]);
fflush(stdout); // This line prints fine
positions3 = positions2;
destroy_array(positions2);
printf("%d %d %d", positions3[0][1], positions3[1][1], positions3[2][1]);
fflush(stdout); // This line triggers a segfault

有人知道问题可能是什么?

您一次调用 calloc,然后一次调用 malloc,但随后您正在调用 free n 1次(当然,您可以释放相同的值,arr[1] n次)。每个malloccalloc应该有一个free

void destroy_array(int** arr)
{
  free(arr[0]);
  free(arr);
}

此行

rows[i] = values + (i * m * sizeof(int));

应该是

rows[i] = values + (i * m);

背后的原因是values是一个打字指针,即指向int。将1添加到其上增加了1 * sizeof (int)。您的代码假定仅将其增加1

这是基本的指针算术:http://cslibrary.stanford.edu/104/; - )

因此,您甚至在第一次致电free()之前就遇到了未定义的行为。


malloc/callocfree遵循模式:

一个分配 ->一个释放

因此,释放可能看起来像这样:

free(*arr); /* Free what had been allocated to "values". */
free(arr); /* Free what had been allocated to "rows". */

您显示的代码确实有所不同,如 zindorsky的答案。


关于您的编辑:

这个

positions_last = positions;

不复制数组,其元素,而只是对数组第一成员的引用。因此,如果您也将positions划分为positions_last点释放,那就是Invalif内存。访问它会引起UB,就像此行所做的那样:

printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);

学习的课程:在C中,一个人不能通过简单的作业复制数组

最新更新