2

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?

Yu Hao
123k50 gold badges252 silver badges305 bronze badges
asked Dec 20, 2015 at 7:31
5
  • 3
    You don't have a 2D array. You have an array of pointers to other arrays. Commented Dec 20, 2015 at 7:33
  • 1
    try int (*a)[2] = calloc( 2, sizeof(*a)); /*memset( a, 0, 4 * sizeof( int) );*/ ` Commented Dec 20, 2015 at 7:37
  • Compile with all warnings & debug info (gcc -Wall -Wextra -g) then use a debugger (gdb) Commented Dec 20, 2015 at 8:09
  • that's an array of pointers to another array, not 2D array Commented Dec 20, 2015 at 8:33
  • if some answer helps you, accept it by clicking the green check Commented Oct 25, 2016 at 9:12

3 Answers 3

4

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.

answered Dec 20, 2015 at 7:36
Sign up to request clarification or add additional context in comments.

Comments

4

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.

answered Dec 20, 2015 at 8:25

Comments

2

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.

answered Dec 20, 2015 at 7:56

1 Comment

1) Certainly the 2nd 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.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.