释放动态2D数组在C

时间:2015-10-17 23:52:11

标签: c multidimensional-array free dynamic-arrays

当我运行如下代码时:

#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的2d动态数组(即指向动态分配的指针数组的指针,每个指针指向一个动态分配的整数数组)。然后,递归地为每个数组**(ary + i)的第0个元素分配当前值count

下半部分将反向迭代,释放ary的每个元素,反过来它是malloc&#39; 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)变成了看起来像某个内存地址(只是轻微地)一旦它离开第一个循环,这个2d数组占用了什么界限。

如果我摆脱了第二个循环而只是尝试直接释放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,如果相关的话。

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

ari是指针数组的指针,因此元素的大小是指针。在您的代码中,您使用的sizeof **aryint

    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()调用很有可能完全失败。