[英]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 模式在解释为
int
或double
等数字类型时产生零值,因此使用 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.