简体   繁体   English

为什么 memset 部分初始化?

[英]Why memset init partially?

I'm trying to init a int **a with 0 by memset .我正在尝试通过memset用 0 初始化一个int **a But the result is some item is not zero.但结果是某些项目不为零。
Source code源代码

#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 Output

0 0 0 
0 0 0 
0 1610612736 0

Update 1更新 1

I'm trying to malloc contiugous in two ways as suggested.我正在尝试按照建议的两种方式使malloc连续。 But in method 2 a exception thrown when init array.但是在方法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)

This cannot possibly work other than by amazing fluke:除了惊人的侥幸之外,这不可能奏效:

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

You have simulated a multi-dimensional array by allocating a vector of pointers to separately allocated rows.您通过将指针向量分配给单独分配的行来模拟多维数组。 But in the above expression, you're assuming that the memory is linear (allocated all in one piece).但是在上面的表达式中,您假设 memory 是线性的(全部分配在一块)。 The memset writes beyond the end of the a[0] row, causing undefined behavior. memset写入超出a[0]行的末尾,导致未定义的行为。

The correct approach is to iterate over the array of pointers, and individually memset each row:正确的方法是遍历指针数组,并单独memset每一行:

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

This memset action can be hoisted into the original loop which allocates the rows;这个memset动作可以提升到分配行的原始循环中; moreover, calloc can be used instead of malloc to make the memset unnecessary.此外,可以使用calloc代替malloc以使memset变得不必要。 (The C language requires that an all-zero bit memory pattern produces values of zero when interpreted as a numeric type such as int or double , so initializing numeric arrays to zero with calloc is type safe and portable.) (C 语言要求全零位 memory 模式在解释为intdouble等数字类型时产生零值,因此使用 call 将数字calloc初始化为零是安全的)

Also, there is no <memory.h> header in standard C.此外,标准 C 中没有<memory.h> header。 The malloc function has been declared in <stdlib.h> since before C was first standardized in 1989.自 1989 年 C 首次标准化之前, malloc function 已在<stdlib.h>中声明。

Your memset line assumes that the array of pointers created in your first for loop point to contiguous memory - that is, you assume that, for example, a[1] will point to the memory location immediately following the buffer pointed to by a[0] .您的memset行假设在您的第一个for循环中创建的指针数组指向连续的memory - 也就是说,例如,您假设a[1]将指向紧跟在a[0] .

However, there is no guarantee that this will be the case, As it happens, in some of your cases this is true but, ultimately, working on this assumption will cause Undefined Behaviour !但是,不能保证会出现这种情况,碰巧的是,在您的某些情况下,这是正确的,但最终,在这个假设上工作会导致未定义的行为

To correct the problem, you should initialize each memory buffer separately;要纠正该问题,您应该分别初始化每个 memory 缓冲区; the simplest way would be to do it as your create each one:最简单的方法是在创建每一个时这样做:

#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");
    }
}

Feel free to ask for further clarification and/or explanation.随时要求进一步澄清和/或解释。

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

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