I used memset() to fill a 2D integer array as below.
int main(){
int** a = calloc( 2, sizeof(int*) );
int i = 0;
for( ; i<2; i++ ){
a[ i ] = calloc( 2, sizeof( int ) );
}
memset( a, 0, 4 * sizeof( int ) ) ;
for( i = 0; i < 2; i++ ){
int j = 0;
for( ; j < 2; j++ ){
printf( "%d ", a[i][j] );
}
printf("\n");
}
}
Output:
Segmentation fault
But if I replace memset( a, 0, 4 * sizeof( int ) ) with:
for( i = 0; i < 2; i++ ){
int j = 0;
for( ; j < 2; j++ ){
a[ i ][ j ] = 0;
}
}
The output is correct:
0 0
0 0
Can anybody tell me why the memset() did not work there?
3 Answers 3
While allocating memory, you have allocated 2, sizeof(int*) amount to a, and while doing memset(), you use 4 * sizeof(int). They necessarily do not represent same amount of memory (more importantly, that's even not what you wanted) hence there's a over-run of allocated memory. This invokes undefined behavior which causes the segmentation fault.
Having said that, you don't need to memset() a calloc()ed memory to 0. It already is.
Comments
When you write like this
int** a = calloc( 2, sizeof(int*) );
int i = 0;
for( ; i<2; i++ ){
a[ i ] = calloc( 2, sizeof( int ) );
}
You get in the memory something like this
+--+ +--+--+
a[0] | |-----> | | |
+--+ +--+--+
a[1] | |
+--+
\ +--+--+
+---> | | |
+--+--+
memset expects memory to be as a continuous memory block, but that is not what
you are giving it, so with memset(a,0,4*sizeof(int)) you are writing beyond
a[1] out in the blue.
With a[0][1] you are doing two deferences, one for the first vector a[0]..a[1] and one for the second vector that is why it works in your for-loop.
Comments
There is no guarantee that all your different allocations are contiguous to each other. The only way to initialize correctly your memory is to initialize each part that was allocated. You can use memset but this way:
int** a = calloc( 2, sizeof(int*) );
memset( a, 0, 2 * sizeof( int* ) ) ; // initialize the two pointers
int i = 0;
for( ; i<2; i++ ){
a[ i ] = calloc( 2, sizeof( int ) );
memset( a[i], 0, 2 * sizeof( int ) ) ; // initializes the two ints
}
Note that initializing to zero is not necessary since you used calloc.
1 Comment
memset( a, 0, 2 * sizeof( int ) ) ; // initializes the two ints --> memset( a[i], 0, 2 * sizeof( int ) ) ; 2) Why memset() the arrays at all with 0 as calloc() zeros the allocated memory.
int (*a)[2] = calloc( 2, sizeof(*a)); /*memset( a, 0, 4 * sizeof( int) );*/`gcc -Wall -Wextra -g) then use a debugger (gdb)