【问题标题】:Freeing dynamic 2D array not working as expected in C释放动态二维数组在 C 中没有按预期工作
【发布时间】:2016-01-16 12:37:26
【问题描述】:

当我运行如下代码时:

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

int main (void)
{
    int i, count = 0x09;
    int sizei = 5, sizej = 2;

    int **ary = malloc (sizei * sizeof **ary);
    for (i = 0; i < sizei; i++) {
        *(ary + i) = malloc (sizej * sizeof *(ary + i));
        **(ary + i) = ++count;
        printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
    }

    puts("----");
    for (i = sizei - 1; i >= 0; i--) {
        printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
        free (*(ary + i));   
    }
    puts("----");

    free (ary);
    return 0;
}

我希望前半部分会创建一个名为ary 的二维动态整数数组(即指向动态分配的指针数组的指针,每个指针都指向动态分配的整数数组)。每个数组 **(ary + i) 的第 0 个元素将被递归地分配给 count 的当前值。

后半部分将反向迭代,释放 ary 的每个元素,反向释放它是 malloc'd,然后释放 ary 本身。

这似乎工作正常,直到我尝试释放 *(ary + 0),此时我得到一个双重释放/损坏错误。我已经包含了输出。

  0 |0x1d6f010| +a+ 
  1 |0x1d6f018| +b+ 
  2 |0x1d6f020| +c+ 
  3 |0x1d6f028| +d+ 
  4 |0x1d6f030| +e+ 
----
  4 |0x1d6f030| +e+ 
  3 |0x1d6f028| +d+ 
  2 |0x1d6f020| +c+ 
  1 |0x1d6f018| +b+ 
  0 |0x1d6f010| +1d6f0b0+ 
*** Error in `./a.out': double free or corruption (out): 0x0000000001d6f030 ***

我很好奇为什么 ary 的第 0 个元素的第 0 个元素(即 *(*(ary + 0) + 0)) 或只是 **ary)变成了看起来像一些内存地址(只是稍微)超出范围的内存地址退出第一个循环后的二维数组。

如果我摆脱第二个循环并尝试直接释放 ary 而不首先释放其任何元素,我会得到类似:

  0 |0x1d6f010| +a+ 
  1 |0x1d6f018| +b+ 
  2 |0x1d6f020| +c+ 
  3 |0x1d6f028| +d+ 
  4 |0x1d6f030| +e+ 
----
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000001d6f010 ***

我不明白我在这里做错了什么。使用数组表示法会有所不同吗?如果可能的话,我需要任何解决方案来让每个数组的动态长度独立于ary 的其余元素的长度。 ary 的数字元素在编译时也不一定知道。如果相关,我正在使用 gcc 4.9。

【问题讨论】:

    标签: c multidimensional-array free dynamic-arrays


    【解决方案1】:

    ari 是指向指针数组的指针,因此元素的大小是指针。在您的代码中,您使用 sizeof **ary 这是一个 int

        int **ary = malloc (sizei * sizeof **ary);
    

    对于每个指向int 元素数组的指针。在这些指针的 malloc 中,您使用 sizeof *(ary+i) 这是指向 int 的指针

            *(ary + i) = malloc (sizej * sizeof *(ary + i));
    

    sizeof(int) 并不总是与 sizeof(int*) 相同。事实上,在大多数 64 位系统上,我怀疑你使用的是 sizeof(int)==4 和 sizeof(int*)==8。

    我的猜测是您正在使用这样的系统,因此,您没有为主 ari 指针分配足够的内存,并且您正在用值溢出它,从而破坏了关键内存管理数据的内容,因此未来malloc() 和 free() 调用很有可能完全失败。

    【讨论】:

      【解决方案2】:

      问题 1

      int **ary = malloc (sizei * sizeof **ary);
      

      等价于

      int **ary = malloc (sizei * sizeof int);
      

      如果您系统中的sizeof 指针小于sizeof(int),您最终会越界访问内存。

      你需要使用:

      int **ary = malloc (sizei * sizeof *ary);
      

      int **ary = malloc (sizei * sizeof(int*));
      

      问题 2

      *(ary + i) = malloc (sizej * sizeof *(ary + i));
      

      需要

      *(ary + i) = malloc (sizej * sizeof **(ary + i));
      

      *(ary + i) = malloc (sizej * sizeof int);
      

      ary[i] = malloc (sizej * sizeof *ary[i]);
      

      ary[i] = malloc (sizej * sizeof int);
      

      【讨论】:

        猜你喜欢
        • 2018-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        • 2011-08-05
        • 2020-01-18
        相关资源
        最近更新 更多