1

im trying to use a dynamic array to calculate average with credits but my program crashes when i run with the values:

  • 2 1 1 1 1 3 1 1

it doesn't crash if i do:

  • 2 1 1 1 1 4 1 1 1 1

if i remove the for loop with the free(); inside

for (i=0 ; i<classes ; i++) 
{   //free each individual 2unit array first
    free(grades[i]);    //This line doesnt work
}

it runs fine but i don't want to do that because im told not to do that.

here's the code, i tried to remove the unnecessary parts as best as i can

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

void fillArray(int **grades,int start,int finish)
{   
    int i;
    for(i=start;i<finish;i++)
    {
        printf("Enter grade for Class %d: ",i+1);
        scanf("%d",&grades[i][0]);
        printf("Enter Credit for Class %d: ",i+1);
        scanf("%d",&grades[i][1]);

    }
}
void expandArray(int **grades,int oldSize,int newSize)
{
    *grades = (int *)realloc(*grades,newSize*sizeof(int*));    //expanding the pointer array
    int i;
    for(i=oldSize;i<newSize;i++)   //filling it with 2 unit arrays per class
    {
        grades[i] = (int *)malloc(2*sizeof(int));   
    }
    fillArray(grades,oldSize,newSize);  
}

int main()
{
    int classes,oldClasses;
    printf("Enter number of classes: ");
    scanf("%d",&classes);

    int **grades = (int **)malloc(classes*sizeof(int*));   //creating an array to store 2unit arrays(pointer array)
    int i;
    for(i=0;i<classes;i++)   //filling the pointer array with 2 unit arrays per class
    {
        grades[i] = (int *)malloc(2*sizeof(int));
    }

    printf("Enter grades for each classes: \n");
    fillArray(grades,0,classes);    // this 0 here means we start at the index 0, that parameter is later used to start at the lastIndex+1


    oldClasses = classes;   // copied the value of classes to oldClasses instead of taking the new one as newClasses to avoid confusion.
    printf("Enter new number of classes: ");
    scanf("%d",&classes);
    expandArray(grades,oldClasses,classes);
    printf("This line works!");
    for (i=0 ; i<classes ; i++) 
    {   //free each individual 2unit array first
        free(grades[i]);    //This line doesnt work
    }
    printf("This won't get printed with the value 3...");
    free(grades);   //free the pointer array (This one also works)

    return 0;
}
Yunus Gulcu
  • 92
  • 10
  • 2
    Don't cast the return value of `malloc()`. See http://stackoverflow.com/q/605845/3488231 – user12205 Dec 18 '14 at 13:06
  • i removed the casts on all the 'malloc()' s , i also tried removing the cast on 'realloc()' .But i still get the crash – Yunus Gulcu Dec 18 '14 at 13:19
  • Just saying that it's not something you should do. Not saying that it's the cause of your crash. Otherwise I would have posted it as an answer, not a comment. – user12205 Dec 18 '14 at 13:24
  • oh ok, the reason i was casting is because i was told my code would be incompatible with the old standarts if i didn't. thanks for the info though,i will try removing the cast if i run into problems in the future – Yunus Gulcu Dec 18 '14 at 13:29
  • The gave you the wrong hint then, in C `void*` has always converted to any data pointer type. The only context where this poses problems is C++, but you shouldn't use `malloc` there, anyhow. – Jens Gustedt Dec 18 '14 at 14:20

2 Answers2

0

Check for value of classes inside main()

When you get number of classed the second time you are reallocating memory within the function expandArray() and this expansion is not visible outside of that function so when you are freeing you might try to free some unallocated memory hence the crash.

Gopi
  • 19,784
  • 4
  • 24
  • 36
0

expandArray is actually updating grades which is an int** but inside you are updating *grades: You are expanding the first array from 2 grades to newSize grades while you wanted to add a new entire class.

You want to pass the address of the object you want to modify in the function, so you should pass a int***.

void expandArray(int ***grades,int oldSize,int newSize)
{
    grades = realloc(grades, newSize*sizeof(int*));
    // ...
}

Note: But 3D pointers is usually not a good practice : you might want to modify expandArray so it returns a new int**.

n0p
  • 3,399
  • 2
  • 29
  • 50
  • when i do `grades = realloc(grades, newSize*sizeof(int));` inside the main it works but when i move the same thing to the function it doesnt do i need to send `int ***grades` to the function? – Yunus Gulcu Dec 18 '14 at 15:20
  • You need to send the address of `int ** grades` : `expandArray(&grades,oldClasses,classes);` (I had a typo in my answer : I updated the signature of `expandArray`) – n0p Dec 18 '14 at 15:31
  • ok i think i get it now. the adress of `int** grades` is of type `int***` thats why we use `int***` in the function.Everything now works fine if i take `fillArray(grades,oldSize,newSize);` out of the function and call it in the main.Thanks – Yunus Gulcu Dec 18 '14 at 16:10