Reputation: 373
I'm trying to init a int **a
with 0 by memset
. 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
0 0 0
0 0 0
0 1610612736 0
Update 1
I'm trying to malloc
contiugous in two ways as suggested. But in method 2 a exception thrown when init array.
#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)
Upvotes: 0
Views: 106
Reputation: 58617
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). The memset
writes beyond the end of the a[0]
row, causing undefined behavior.
The correct approach is to iterate over the array of pointers, and individually memset
each row:
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; moreover, calloc
can be used instead of malloc
to make the memset
unnecessary. (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.)
Also, there is no <memory.h>
header in standard C. The malloc
function has been declared in <stdlib.h>
since before C was first standardized in 1989.
Upvotes: 3
Reputation: 51864
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]
.
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; 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.
Upvotes: 2