【问题标题】:double free or corruption 3d array in CC中的双重免费或损坏的3d数组
【发布时间】:2015-04-03 17:14:46
【问题描述】:

我在释放 3d 数组时收到“双重释放或损坏”错误。谁能告诉我代码中的问题在哪里? 数组的大小为 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);

程序运行良好,但最后我收到错误“双重释放或损坏(!prev):0x08cd24f8” 中止(核心转储)。

【问题讨论】:

标签: c arrays malloc free corruption


【解决方案1】:

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

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

但是你把它当作它有N 元素:

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

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

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

也不要转换malloc 的返回值。此外,您的代码缺少错误处理,如果分配失败,则会中断。

【讨论】:

    【解决方案2】:

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

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

    如果 N>2...,您将覆盖未分配的空间...

    【讨论】:

      【解决方案3】:

      问题就在这里:

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

      【讨论】:

      • 它是一个 2*NN 数组,而不是 NN*N。
      【解决方案4】:

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

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

      不要投malloc()

      【讨论】:

        【解决方案5】:

        正如其他人指出的那样,导致该错误的具体问题是您将具有 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 年的编译器。

        【讨论】:

        • 非常感谢您的宝贵意见。你在那里提供了非常好的观点。干杯
        猜你喜欢
        • 2016-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-25
        • 2013-03-07
        相关资源
        最近更新 更多