繁体   English   中英

为什么 memset 部分初始化?

[英]Why memset init partially?

我正在尝试通过memset用 0 初始化一个int **a 但结果是某些项目不为零。
源代码

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

int main()
{
    int aSize = 3;
    int **a = (int **)malloc(sizeof(int *)*aSize);
    for (int i=0; i<aSize; i++) {
        a[i]=(int *)malloc(sizeof(int)*aSize);
    }

    memset(a[0], 0, aSize*aSize*sizeof(int));

    for (int i=0; i<aSize; i++) {
        for (int j=0; j<aSize; j++) {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
}

Output

0 0 0 
0 0 0 
0 1610612736 0

更新 1

我正在尝试按照建议的两种方式使malloc连续。 但是在方法2中,初始化数组时抛出了异常。

#include <stdio.h>
#include <stdlib.h>
#include <strings.h> // memset header changed
// method 1
int **a = malloc(sizeof(int *)*aSize);
for (int i=0; i<aSize; i++) {
    a[i]=malloc(sizeof(int)*aSize);
    memset(a[i], 0, aSize*sizeof(int));
}

for (int i=0; i<aSize; i++) {
    for (int j=0; j<aSize; j++) {
        printf("%d ", a[i][j]);
    }
    printf("\n");
}

for (int i=0; i<aSize; i++) {
    free(a[i]);
}

free(a);

// method 2
a = malloc(sizeof(int *)*aSize + sizeof(int)*aSize);
memset(a[0], 0, aSize*aSize*sizeof(int)); // Exception: EXC_BAD_ACCESS (code=1, address=0x1c)

除了惊人的侥幸之外,这不可能奏效:

memset(a[0], 0, aSize*aSize*sizeof(int));

您通过将指针向量分配给单独分配的行来模拟多维数组。 但是在上面的表达式中,您假设 memory 是线性的(全部分配在一块)。 memset写入超出a[0]行的末尾,导致未定义的行为。

正确的方法是遍历指针数组,并单独memset每一行:

for (i = 0; i < aSize; i++)
   memset(a[i], 0, aSize * sizeof a[i]);

这个memset动作可以提升到分配行的原始循环中; 此外,可以使用calloc代替malloc以使memset变得不必要。 (C 语言要求全零位 memory 模式在解释为intdouble等数字类型时产生零值,因此使用 call 将数字calloc初始化为零是安全的)

此外,标准 C 中没有<memory.h> header。 自 1989 年 C 首次标准化之前, malloc function 已在<stdlib.h>中声明。

您的memset行假设在您的第一个for循环中创建的指针数组指向连续的memory - 也就是说,例如,您假设a[1]将指向紧跟在a[0] .

但是,不能保证会出现这种情况,碰巧的是,在您的某些情况下,这是正确的,但最终,在这个假设上工作会导致未定义的行为

要纠正该问题,您应该分别初始化每个 memory 缓冲区; 最简单的方法是在创建每一个时这样做:

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

int main()
{
    int aSize = 3;
    int **a = (int **)malloc(sizeof(int *)*aSize);
    for (int i=0; i<aSize; i++) {
        a[i]=(int *)malloc(sizeof(int)*aSize);
         memset(a[i], 0, aSize*sizeof(int)); // Set each buffer to all zeros here!
    }

//  memset(a[0], 0, aSize*aSize*sizeof(int)); // This will cause undefined behaviour

    for (int i=0; i<aSize; i++) {
        for (int j=0; j<aSize; j++) {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
}

随时要求进一步澄清和/或解释。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM