Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Malloc'ing Arrays and then Free'ing them?

I'm currently messing around with c I'm having a few hiccups in the pointer usage and syntax area.

Below, i am (trying) to create an array of pointers to integer arrays, then, direct each pointer to an array created via malloc().

After the arrays have been created i then for loop through each cell, assigning a value.

Now, all of this seems to be working, but when it comes to then using free() to take back the memory, the program crashes.

I have noticed that if i malloc() the array memory and then immediately call free() on them, the program executes without problem. When however I malloc(), assign values and THEN call free() the crash will occur. (Segmentation fault).

Below is the code that works, malloc() then immediately free()ing

int (*ptrArr[5])[5];

for(int i=0; i<5; i++)
    ptrArr[i] = malloc(sizeof(int) * 5);

for(int i=0; i<5; i++)
    printf("ptrArr[%d][%x]->[%x]\n", i, &ptrArr[i], &*ptrArr[i]);
printf("\n");

for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);  
    }
    printf("\n");
}

for(int i=4; i>=0; i--)
    free(ptrArr[i]);

the above executes as i expected it to, but when I assign values to cells and then try and call free afterwards, a segmentation fault is generated:

int (*ptrArr[5])[5];

for(int i=0; i<5; i++)
    ptrArr[i] = malloc(sizeof(int) * 5);

for(int i=0; i<5; i++)
    printf("ptrArr[%d][%x]->[%x]\n", i, &ptrArr[i], &*ptrArr[i]);
printf("\n");

for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);  
    }
    printf("\n");
}

int loop = 5;
for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        *ptrArr[i][j] = (loop + (i*j));
        ++loop;
    }
}

printf("\n");
for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);
    }
    printf("\n");
}

for(int i=4; i>=0; i--)
{
    printf("Freeing ptrArr[%x]\n", i);
    free(ptrArr[i]);
}

I think I'm either misunderstanding the

int (*ptrArr[5])[5];

declaration, which I intended was an array of 5 pointers, each pointing to an integer array, or im not assigning values to cells correctly, instead, corrupting memory which causes the free() to fail.

Any help would be appreciated, I hope the question is clear and succinct.

Thanks.

like image 474
T.Goodall Avatar asked Oct 31 '22 15:10

T.Goodall


1 Answers

The way I approach this type of problem is to print out the sizeof the various suspects, like this

int (*test[5])[5];

printf( "%zu ", sizeof(test) );
printf( "%zu ", sizeof(test[0]) );
printf( "%zu\n", sizeof(test[0][0]) );

The result is 40 8 20. (Note that on my machine an int is 4 bytes and a pointer is 8 bytes.)
So that tells me that test is an array of 5 pointers. It logically follows that test[0] is a single pointer. But what's interesting is that test[0][0] is an array of 5 ints.

If I add the following line of code

printf( "%zu\n", sizeof(test[0][0][0]) );

the output is 4, i.e. test[0][0][0] is a single int. From that we conclude that the declaration int (*test[5])[5] is declaring a three dimensional array, which is not what you intended.


So let's try a simpler declaration, like this

int (*test)[5];

printf( "%zu ", sizeof(test) );
printf( "%zu ", sizeof(test[0]) );
printf( "%zu\n", sizeof(test[0][0]) );

The output is 8 20 4, which is to say that test is a single pointer, test[0] is an array of 5 ints, and test[0][0] is a single int. We conclude that int (*test)[5] declares a two dimensional array.


The next question is how to we allocate memory for the array. If we do this

test = malloc( 5 * sizeof(int) );

then we have an array that has 1 row and 5 columns, basically a one-dimensional array.

To get a two-dimensional array with N rows, we need

test = malloc( N * 5 * sizeof(int) );

Then we can fill, print, and free the array like this

int N = 5;
for ( int row = 0; row < N; row++ )
    for ( int col = 0; col < 5; col++ )
        test[row][col] = (row+5)*10 + col;

for ( int row = 0; row < N; row++ )
{
    for ( int col = 0; col < 5; col++ )
        printf( "%2d ", test[row][col] );
    printf( "\n" );
}

free( test );
like image 156
user3386109 Avatar answered Nov 15 '22 06:11

user3386109