1

I am writing this program to print square,cube,multiples of 4, multiples of 5 into a 2 dimensional array. I am always getting a segmentation fault error. Can you please help explain what is going on? The program does not print all the elements of the 2D array. It ends in segmentation fault after 4th or 6th row.

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

void numbers(int ***arr,int nrows,int ncols);
void square(int ***arr,int nrows,int ncols);
void cube(int ***arr,int nrows,int ncols);
void multiples_of_4(int ***arr,int nrows,int ncols);
void multiples_of_5(int ***arr,int nrows,int ncols);
void free_our_ptr(int ***arr,int nrows,int ncols);


int main(void)
{

    int i=0;

    int nrows = 0;
    int ncols = 0;

    int menu_choice = 0;

    int **arr;

    printf("\nGet number of rows : ");
    scanf("%d",&nrows);

    if(nrows > 10)
    {
        printf("\nRows should be less than 10 ");
        exit(0);

    }

    printf("\nGet number of columns : ");
    scanf("%d",&ncols);

    if(ncols > 10)
    {
        printf("\nColumns should be less than 10 ");
        exit(0);

    }

    /******* Dynamic memory allocation for array ***********/

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

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

    /********************************************************/

    printf("\nThese are your choices : ");
    printf("\nFill with Integers ---------------- 1");
    printf("\nFill with Squares  ---------------- 2");
    printf("\nFill with Cubes ------------------- 3");
    printf("\nFill with Multiples of 4 ---------- 4");
    printf("\nFill with Multiples of 5 ---------- 5");
    printf("\n\nEnter your choice : ");
    scanf("%d",&menu_choice);

    switch(menu_choice)
    {
    case 1:
        numbers(&arr,nrows,ncols);
        break;

    case 2:
        square(&arr,nrows,ncols);
        break;

    case 3:
        cube(&arr,nrows,ncols);
        break;

    case 4:
        multiples_of_4(&arr,nrows,ncols);
        break;

    case 5:
        multiples_of_5(&arr,nrows,ncols);
        break;

    default :
        printf("\nInvalid Choice, exiting program");
        free(arr);
        exit(0);
    }
    exit(0);

}

void numbers(int ***array,int nrows,int ncols)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;
    arr = *array;

    for(i=0;i<nrows;i++)
    {
        printf("\n");
        for(j=0;j<ncols;j++)
        {

            arr[i][j] = number;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }
    free_our_ptr(&arr,nrows,ncols);


}

void square(int ***array,int nrows,int ncols)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;
    arr = *array;

    for(i=0;i<nrows;i++)
    {
        printf("\n");
        for(j=0;j<ncols;j++)
        {

            arr[i][j] = number * number;
            printf("%d\t",arr[i][j]);
            ++number;
        }
    }
    free_our_ptr(&arr,nrows,ncols);
}


void cube(int ***array,int nrows,int ncols)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;
    arr = *array;

    for(i=0;i<nrows;i++)
    {
        printf("\n");
        for(j=0;j<ncols;j++)
        {

            arr[i][j] = number * number * number;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }
    free_our_ptr(&arr,nrows,ncols);
}

void multiples_of_4(int ***array,int nrows,int ncols)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;
    arr = *array;

    for(i=0;i<nrows;i++)
    {
        printf("\n");
        for(j=0;j<ncols;j++)
        {

            arr[i][j] = number * 4;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }
    free_our_ptr(&arr,nrows,ncols);
}

void multiples_of_5(int ***array,int nrows,int ncols)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;
    arr = *array;

    for(i=0;i<nrows;i++)
    {
        printf("\n");
        for(j=0;j<ncols;j++)
        {

            arr[i][j] = number * 5;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }
    free_our_ptr(&arr,nrows,ncols);
}

void free_our_ptr(int ***arr,int nrows,int ncols)
{
    int i;
    for(i=0;i<nrows;i++)
    {
        free(arr[i]);
    }
    free(arr);
}

I tried the suggestions, removed free_our_ptr() function altogether and freed the memory in main() itself. On ubuntu linux gcc, it gives a segmentation fault error. However, on Visual Studio-Windows7, runs perfectly fine, no errors in any test cases. Below is the modified code.

#include<stdlib.h>

void numbers(int ***arr,int nrows,int ncols);
void square(int ***arr,int nrows,int ncols);
void cube(int ***arr,int nrows,int ncols);
void multiples_of_4(int ***arr,int nrows,int ncols);
void multiples_of_5(int ***arr,int nrows,int ncols);

int main(void)
{

    int i=0;

    int nrows = 0;
    int ncols = 0;

    int menu_choice = 0;

    int **arr;

    printf("\nGet number of rows : ");
    scanf_s("%d",&nrows);

    if(nrows > 10)
    {
        printf("\nRows should be less than 10 ");
        exit(0);

    }

    printf("\nGet number of columns : ");
    scanf_s("%d",&ncols);

    if(ncols > 10)
    {
        printf("\nColumns should be less than 10 ");
        exit(0);

    }

    printf("\nNumber of rows = %d",nrows);
    printf("\nNumber of cols = %d",ncols);

    /******* Dynamic memory allocation for array ***********/

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

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

    /********************************************************/

    printf("\nThese are your choices : ");
    printf("\nFill with Integers ---------------- 1");
    printf("\nFill with Squares  ---------------- 2");
    printf("\nFill with Cubes ------------------- 3");
    printf("\nFill with Multiples of 4 ---------- 4");
    printf("\nFill with Multiples of 5 ---------- 5");
    printf("\n\nEnter your choice : ");
    scanf_s("%d",&menu_choice);

    switch(menu_choice)
    {
    case 1:
        numbers(&arr,nrows,ncols);
        break;

    case 2:
        square(&arr,nrows,ncols);
        break;

    case 3:
        cube(&arr,nrows,ncols);
        break;

    case 4:
        multiples_of_4(&arr,nrows,ncols);
        break;

    case 5:
        multiples_of_5(&arr,nrows,ncols);
        break;

    default :
        printf("\nInvalid Choice, exiting program");
        free(arr);
        exit(0);
    }

    free(arr);

    exit(0);

}

void numbers(int ***array,int num_rows,int num_columns)
{
    int i=0;
    int j=0;

    int number = 1;
    int **arr;
    int r1 = num_rows;
    int c1 = num_columns;
    arr = *array;

    printf("\nNumber of rows = %d",r1);
    printf("\nNumber of cols = %d",c1);

    for(i=0;i<r1;i++)
    {
        printf("\n");
        for(j=0;j<c1;j++)
        {

            arr[i][j] = number;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }


}

void square(int ***array,int num_rows,int num_columns)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;

    int r2 = num_rows;
    int c2 = num_columns;

    arr = *array;

    printf("\nNumber of rows = %d",r2);
    printf("\nNumber of cols = %d",c2);

    for(i=0;i<r2;i++)
    {
        printf("\n");
        for(j=0;j<c2;j++)
        {

            arr[i][j] = number * number;
            printf("%d\t",arr[i][j]);
            ++number;
        }
    }

}


void cube(int ***array,int num_rows,int num_columns)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;

    int r3 = num_rows;
    int c3 = num_columns;

    arr = *array;

    printf("\nNumber of rows = %d",r3);
    printf("\nNumber of cols = %d",c3);

    for(i=0;i<r3;i++)
    {
        printf("\n");
        for(j=0;j<c3;j++)
        {

            arr[i][j] = number * number * number;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }

}

void multiples_of_4(int ***array,int num_rows,int num_columns)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;

    int r4 = num_rows;
    int c4 = num_columns;

    arr = *array;

    printf("\nNumber of rows = %d",r4);
    printf("\nNumber of cols = %d",c4);

    for(i=0;i<r4;i++)
    {
        printf("\n");
        for(j=0;j<c4;j++)
        {

            arr[i][j] = number * 4;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }

}

void multiples_of_5(int ***array,int num_rows,int num_columns)
{
    int i=0;
    int j=0;
    int number = 1;
    int **arr;

    int r5 = num_rows;
    int c5 = num_columns;

    arr = *array;

    printf("\nNumber of rows = %d",r5);
    printf("\nNumber of cols = %d",c5);

    for(i=0;i<r5;i++)
    {
        printf("\n");
        for(j=0;j<c5;j++)
        {

            arr[i][j] = number * 5;
            printf("%d\t",arr[i][j]);
            number++;
        }
    }

}

2 Answers2

1
arr = (int **) malloc ( nrows * sizeof(int));

is not right. It needs to be

arr = (int **) malloc ( nrows * sizeof(int*));
                                       ^^^^ an array of pointers to int.

The first one allocates enough space for nrows of ints.
The second one allocates enough space for nrows of int*s.

Also, since you are using C, not C++, don't cast the return value of malloc. See Do I cast the result of malloc?

Just use:

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

The function free_our_ptr is not right either.

void free_our_ptr(int ***arr,int nrows,int ncols)
{
    int i;
    for(i=0;i<nrows;i++)
    {
        free(arr[i]);
             ^^^^ Not right
    }
    free(arr);
         ^^^ Not right.
}

My suggestion to fix it is to change the interface to:

void free_our_ptr(int **arr, int nrows, int ncols);
                      ^^^^ Use int**, not int***.

Then, the code in the function will work. However, you'll need to change all the places it gets used.

Instead of calling it as:

free_our_ptr(&arr,nrows,ncols);

you'll need to call it as:

free_our_ptr(arr,nrows,ncols);
             ^^^ No &
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

You pass a pointer to the pointer which refers to the dynminc allocated memory to your function free_our_ptr. Either yo dereference the pointer inside the function:

void free_our_ptr(int ***arr,int nrows,int ncols)
{
    int i;
    for(i=0;i<nrows;i++)
    {
        free((*arr)[i]);
           // ^
    }
    free(*arr);
      // ^ type of arr is int***
}

Or you pass the pointer to the dynamic allocated memory to your function free_our_ptr:

void free_our_ptr( int **arr,int nrows,int ncols )
                    // ^^ 
{
    int i;
    for(i=0;i<nrows;i++)
    {
        free( arr[i] );
    }
    free( arr );
}

Apart from this you have to allocate your memory like this:

arr = malloc( nrows * sizeof(int*) );
                             // ^  type of arr is  int** and type of an element is int*
for(i=0;i<nrows;i++)
{
    arr[i] = malloc( ncols * sizeof(int) );
}

Further I recommend to remove free_our_ptr(&arr,nrows,ncols); from your functions numbers, square, cube, multiples_of_4 and multiples_of_5. Free the memory in main, because you allocataed it in main too.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174