Search code examples
carraysmallocrealloc

program crashes while using realloc


I am given a text file of unknown size and i have to read it till the end, calculate the number of words, letters and some other stuff. To do this i try to read the entire file and save all the words in an array. I am told to use dynamic memory allocation since i don't know the size of the text file beforehand.

Before i get into the algorithm for calculating the words and letters i am trying to make the dynamic memory allocation work. This is my code:

int main(int argc, char *argv[]) {

    FILE *fp; // file pointer

    //defining a dynamic string array

    char **array = malloc(10 * sizeof(char *)); //10 rows for now, will be   dynamically changed later

    int i,size = 10, current = 0; // current points to the position of the next slot to be filled

    for(i=0; i<10; i++){
        array[i] = malloc(20); //the max word size will be 20 characters (char size = 1 byte)
    }


    fillArray(fp, array, current, size);

    return 0;
}

I define an array of strings, a variable showing its size, and a variable pointing to the slot where the next element will be added. The functions are as follows:

int fillArray(FILE *fp, char **p, int ptr, int size){

    puts("What's the name of the file (and format) to be accessed?\n (It has to be in the same directory as the program)");
    char str[20];
    gets(str);  //getting the answer
    fp = fopen((const char *)str, "r"); //opening file


    int x=0, i=0, j;

    while(x!=EOF){ // looping till we reach the end of the file
        printf("current size: %d , next slot: %d\n", size, ptr);
        if(ptr>=size){
            printf("increasing size\n");
            addSpace(p, &size);
        }
        x = fscanf(fp, "%19s", p[i]);
        puts(p[i]);
        i++;
        ptr++;
    }

}

void addSpace(char **p, int *size){ //remember to pass &size
    //each time this is called, 10 more rows are added to the array
    p = realloc(p,*size + 10);
    int i;
    for(i=*size; i<(*size)+10; i++){
        p[i] = malloc(20);
    }
    *size += 10;
}

void freeSpace(char **p, int ptr){
    //each time this is called, the rows are reduced so that they exactly fit the content
    p = realloc(p, ptr); //remember that ptr points to the position of the last occupied slot + 1

}

At the beginning, the rows of the array are 10. Each time the words of the text don't fit the array, the function addSpace is called adding 10 more rows. The program runs succesfully 3 times (reaching 30 rows) and then crashes.

After using printf's to find out where the program crashes (because i am not used to the debugger yet), it seems that it crashes while trying to add 10 more rows (to 40). I can't figure out the problem or how to fix it. Any help is appreciated.


Solution

  • Classic!

    You are also passing in a double pointer which is reallocd, the address has changed between the caller and callee.

    Also there's a realloc issue.

    p = realloc(p,*size + 10);
    

    If realloc fails, the original pointer to block of memory is clobbered.

    The proper way to do this:

    char **tmp_ptr = realloc(p, *size + 10);
    if (tmp_ptr == NULL){
       perror("Out of memory");
    }else{
        p = tmp_ptr;
    }
    return p;
    

    You can do it another way, either return back the address of the new block or use triple pointers.

    void addSpace(char ***p, int *size){ //remember to pass &size
        //each time this is called, 10 more rows are added to the array
        char **tmp_ptr = realloc(*p, *size + 10);
        if (tmp_ptr == NULL){
           perror("Out of memory");
        }else{
            *p = tmp_ptr;
        }
        int i;
        for(i=*size; i<(*size)+10; i++){
            *p[i] = malloc(20);
        }
        *size += 10;
    }
    

    And from the caller

    addSpace(&p, &size);