对二维数组的“memset”的混淆和“free”的错误

Posted

技术标签:

【中文标题】对二维数组的“memset”的混淆和“free”的错误【英文标题】:Confusion on `memset` of a 2D array and error on `free` 【发布时间】:2018-06-05 19:24:02 【问题描述】:

我使用malloc动态分配内存,使用memset初始化二维数组,使用free释放内存。代码是:

int n1=2,n2=5;
int in1;
float **a;
a = (float **)malloc(n1*sizeof(float *));
for (in1=0;in1<n1;in1++)
    a[in1] = (float *)malloc(n2*sizeof(float));
memset(a[0],0,n1*n2*sizeof(float));
free(*a);free(a);

我运行代码时的第一个问题是: * `./try1' 中的错误:free():下一个大小无效(快速):0x0000000000c06030 *

第二个问题是:因为使用memset 的先决条件是拥有连续的内存。这就是为什么它不适用于 3D 数组(请参阅Error in memset() a 3D array)。但是这里a是一个二维指针或数组,memset的输入是a[0]。我的理解是:

  +---------+---------+-----+--------------+
  | a[0][0] | a[0][1] | ... | a[0][n2 - 1] |
  +---------+---------+-----+--------------+
    ^
    |
 +------+------+-----+-----------+
 | a[0] | a[1] | ... | a[n1 - 1] |
 +------+------+-----+-----------+
           |
           v
         +---------+---------+-----+--------------+
         | a[1][0] | a[1][1] | ... | a[1][n2 - 1] |
         +---------+---------+-----+--------------+

上图显示的是连续内存。所以memset(a[0],0,n1*n2*sizeof(float));可以成功初始化**a。我对吗?如果不连续,怎么初始化成功呢? (来自测试过的开源代码)

【问题讨论】:

你必须遍历数组到free它的指针元素,就像你对malloc它们所做的那样。那么free(a);数组不连续,不是真正的二维数组,还不如是jagged array。 如果多次调用malloc,则不是连续内存。 你拥有的不是二维数组,而是数组数组。它们不占用一块连续的内存,因此您不能使用单个 memset 调用来设置整个内容。您将不得不循环到memsetfree 等,就像您对malloc 内存所做的那样。或者,您可以 malloc 使用单数调用将其全部连续,并使用算术计算行和列。 如果您使用0 作为memset 的数据,那么您可以使用calloc 而不是malloc(尽管free 的问题是相同的。 @Weather Vane 如果像这样迭代地释放: for (in1=0;in1 【参考方案1】:

上图显示的是连续内存。

不,它没有。它显示了两个连续内存区域:a[0][0] -> a[0][n2 - 1] 和 a[1][0] -> a[1][n2 - 1]。

您可以尝试初始化并擦除它们中的每一个:

int n1 = 2, n2 = 5;
int in1;
float **a;
a = (float **)malloc(n1*sizeof(float *));
for (in1 = 0; in1<n1; in1++)
 
    a[in1] = (float *)malloc(n2*sizeof(float));
    memset(a[in1], 0, n2*sizeof(float));

for (in1 = 0; in1<n1; in1++)

    free(*(a+in1));

free(a);

只有在“真实”二维数组的情况下,例如float a[2][5];,您对连续内存的假设是正确的。

【讨论】:

以上是关于对二维数组的“memset”的混淆和“free”的错误的主要内容,如果未能解决你的问题,请参考以下文章

C - memset vs free

二维数组的动态分配(new)初始化(memset)和撤销(delete)

在c++中怎么用memset() 给二维char型数组赋值

将 memset 用于特定行的二维数组

二维字符数组上的 memset

使用 memset 初始化指针元素的二维数组