C 中的双重自由或腐败 3d 数组

double free or corruption 3d array in C

我在释放 3d 数组时遇到 'double free or corruption' 错误。谁能告诉我代码中的问题在哪里? 数组大小为2*N*N。这里 N 的值为 100。即使不转换,结果相同。 这是代码:

// Mallocing 
double ***h = malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
    h[i] = malloc(N * sizeof(double*));
    for(j = 0; j < N; j++) {
        h[i][j] = malloc(N * sizeof(double));
    }
}

// Freeing
for(i = 0; i < N; i++) {
    for(j = 0; j < N; j++) {
        free(h[i][j]);
    }
    free(h[i]);
}
free(h);

程序运行良好,但最后出现错误'double free or corruption (!prev): 0x08cd24f8' 已中止(核心已转储)。

问题在这里:

double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
    // ...
}

你只有 malloc 2 个元素,并迭代 N。 我猜你想拥有大小为 N*N*N 的数组,但你最终得到了 2*N*N

所以这个:

double ***h = (double***) malloc(2 * (sizeof(double**)));

应该是:

double ***h = (double***) malloc(N * (sizeof(double**)));

如果 N = 100 的值与您评论中的一样,那么您需要分配内存来保存 N 个指针到指针,而您只有 2 个。

double ***h =  malloc(N * (sizeof(double*)));

不投malloc()

据我所知,您分配了 2 个项目,然后填充了 N 个项目。

double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
    h[i] = (double**) malloc(N * sizeof(double*));
    ....
    ....
}

你正在覆盖未分配的 space 如果 N>2...

对于第一个维度,您分配了 2 个元素:

double ***h = (double***) malloc(2 * (sizeof(double**)));

但您将其视为具有 N 个元素:

for(i = 0; i < N; i++) {
    h[i] = ...

将最外层循环比较分配 免费更改为:

for(i = 0; i < 2; i++) {

也不要投射 malloc 的 return 值。此外,您的代码缺少错误处理,如果分配失败就会中断。

正如其他人所指出的,导致错误的具体问题是您将具有 2 个元素的维度视为具有 N 个元素。

然而,造成这种情况的核心原因是混淆。我强烈建议您遵守一些规则:

  • 始终将多维数组分配为在相邻内存中分配的真数组Reference.

  • 切勿将多维数组分配为基于指针到指针的查找表,这些查找表在整个堆上都是零散的。它们不仅速度较慢并使代码更难阅读,而且它们实际上并不是数组。您不能将它们与 memcpy() 等一起使用

    不幸的是,有无数糟糕的 C 编程老师和糟糕的书籍宣扬零散的指针到指针查找表。这么多程序员要忘掉这个,太可怕了...

  • 切勿在程序中使用两级以上的间接寻址。永远不应该有这样做的理由,它所做的只是降低程序的可读性(参考 MISRA-C:2012 规则 18.5)。这实际上被称为“三星级节目”,这不是一个美化的词。

  • 永远不要转换 malloc 的结果,因为 it is pointless to do so.

应该做什么:

double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
...
free(array);

示例:

#include <stdio.h>
#include <stdlib.h>

#define X 2
#define Y 3
#define Z 4

int main (void)
{
  double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );

  double count = 0.0;
  for(int x=0; x<X; x++)
  {
    for(int y=0; y<Y; y++)
    {
      for(int z=0; z<Z; z++)
      {
        array[x][y][z] = count++;
        printf("%f ", array[x][y][z]);
      }
      printf("\n");
    }
    printf("\n");
  }

  free(array);

  return 0;
}

要编译这个,你需要一个不超过 16 岁的编译器。