Search code examples
cpass-by-referencedynamic-memory-allocationfreefunction-definition

Segmentation Fault C Arrays and Malloc


I am trying to initialize an arary using a function but I feel like theres something not right about it. When I compile it I am getting Segmentation Fault but not sure where about. Can someone point me in the right direction where I got wrong. I mean if theres a better way to do it feel free to comment. Thank you.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void initialize(int ** arr, int row, int col)
{
    int i; 

    arr = (int **) malloc(sizeof(int *) *col);
    for(i = 0; i < row; i++)
    {
        arr[i] = (int *) malloc(sizeof(int) * row); 
    }

}

void freeArray(int ** arr)
{
    free(arr);
}


int main()
{
    int **arr;
    int r, c; 

    initialize(arr, 3,6); 

    for(r = 0; r <= 3; r++)
    {
        for(c = 0; c <= 6; c++)
        {
            printf("%d ", arr[r][c] = r*c);
        }
        printf("\n");
    }

    freeArray(arr);
}

Solution

  • For starters the function has a bug.

    void initialize(int ** arr, int row, int col)
    {
        int i; 
    
        arr = (int **) malloc(sizeof(int *) *col);
        for(i = 0; i < row; i++)
        {
            arr[i] = (int *) malloc(sizeof(int) * row); 
        }
    
    }
    

    Instead of using the variable col in this statement

        arr = (int **) malloc(sizeof(int *) *col);
    

    you have to use the variable row

    arr = (int **) malloc(sizeof(int *) *row);
    

    And in this statement instead of using the variable row

    arr[i] = (int *) malloc(sizeof(int) * row); 
    

    you have to use the variable col

    arr[i] = (int *) malloc(sizeof(int) * col); 
    

    As for the main problem then the function accepts the pointer declared in main by value. It means that the function deals with a copy of the pointer. Changes of the copy do not reflect on the original pointer.

    Either you need to pass the pointer to the function indirectly through a pointer to it (passing by reference) like

    void initialize(int *** arr, int row, int col)
    {
        int i; 
    
        *arr = (int **) malloc(sizeof(int *) *row);
        for(i = 0; i < row; i++)
        {
            ( *arr )[i] = (int *) malloc(sizeof(int) * col); 
        }
    
    }
    

    and the function is called like

    initialize( &arr, 3,6);
    

    Or it is better when the function allocates arrays and returns a pointer to the arrays like

    int ** initialize( int row, int col)
    {
        int **arr;
    
        arr = (int **) malloc(sizeof(int *) *row);
        for( int i = 0; i < row; i++)
        {
            arr[i] = (int *) malloc(sizeof(int) * col); 
        }
    
        return arr;
    }
    

    and the function is called like

    int **arr = initialize( 3, 6 );
    

    Also in the nested for loops in main there are used invalid conditions

    for(r = 0; r <= 3; r++)
    {
        for(c = 0; c <= 6; c++)
        {
            printf("%d ", arr[r][c] = r*c);
        }
        printf("\n");
    }
    

    You have to write

    for(r = 0; r < 3; r++)
    {
        for(c = 0; c < 6; c++)
        {
            printf("%d ", arr[r][c] = r*c);
        }
        printf("\n");
    }
    

    Also the function freeArray must be declared and defined the following way

    void freeArray(int ** arr, int row)
    {
        if ( arr != NULL )
        {
            for ( int i = 0; i < row; i++ )
            {
                free( arr[i] );
            }
        }
    
        free( arr );
    }
    

    and called like

    freeArray(arr, 3);
    

    Pay attention to that in general you need to check whether memory was successfully allocated before using pointers that point to dynamically allocated memory.