Azzarian
Azzarian

Reputation: 175

Malloc until sudden Termination without error

I am trying to create a program which reads integers from a file with 103690 pairs of integers while skipping lines starting with # and saves them inside an array. Eventhough it does it successfully, it suddenly stops after a specific line (line 5115).

The file looks like this:

#I must
#be
#skipped
8050    6737
8050    7238

The code is:

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

typedef struct {
    int start;
    int end;   
} path;

int doublesize(path* array,int n){
    path* new_array=malloc(n*2*sizeof(path));
    if(new_array==NULL){
        printf("Error allocating memory\n");
        abort();
    }

    for(int i=0;i<n;i++){
        new_array[i]=array[i];
    }
    free(array);
    array=new_array;
    n*=2;
    return n;

}


int main()
{
    int maxsize=10;
    int test;
    path* array=malloc(maxsize*sizeof(path));
    if(array==NULL) {
        printf("Error allocating memory\n");
        abort();
    }


    FILE* fd=fopen("Wiki-Vote2.txt","r");
    if(fd==NULL) {
        printf("Error opening file\n");
        abort();
    }
    char buff[200];
    int counter=0;

    char c;
    while(fgets(buff,200,fd)) {

        c=buff[0];
        if(c=='#') {
            continue;
        }
        test=sscanf(buff,"%d%d",&array[counter].start,&array[counter].end);
        printf("%d\t%d\n",array[counter].start,array[counter].end);
        printf("Read %d numbers\n", test);
        counter++;
        if(counter==maxsize){
           maxsize=doublesize(array,maxsize); 
        }


    }


    fclose(fd);
    free(array);
    return 0;
}

I have tried reducing the number of integers which works but when I used gdb I saw that it returned the signal sigsegv(I use windows).Could the memory be insufficient or is it something else?

Upvotes: 0

Views: 42

Answers (3)

KamilCuk
KamilCuk

Reputation: 141643

Function arguments are passed by value. That includes pointers. So when you do array=new_array; inside doublesize you are assigning to a copy of the pointer array pointer from main. The value of array inside main function stays the same.

You can pass a pointer to the pointer to change it's value.

int doublesize(path **array,int n){
    ...
        // first dereference array, then access element number i
        new_array[i] = (*array)[i];
    }
    // free the array where array points to, ie array in main
    free(*array);
    // assign new value to array
    *array = new_array;
    n *= 2;
    return n;
}


int main()
{
    ...
           // pass array by pointer to let doublesize modify it
           maxsize = doublesize(&array, maxsize); 
    ...
}

I think it could be clearer to change the doublesize function to return the new pointer and to take a pointer to int variable that represents maxsize, like so:

path *doublesize(path *array, int *maxsize){
    int n = *maxsize;
    ...
    free(array);
    // maxsize here points to the variable maxsize in main
    // let's write n * 2 to it
    *maxsize = n * 2;
    // return the new pointer
    return new_array;
}


int main()
{
    ...
           // array is updated with the new value
           // maxsize is updated with 
           array = doublesize(array, &maxsize); 
    ...
}

Upvotes: 3

Ingo Leonhardt
Ingo Leonhardt

Reputation: 9904

In doublesize() you reassign array, but here it's only a local variable, so after the function returns, array in main() still holds the original now freed pointer. So you should pass a double pointer (and use realloc()) so that your function could look like that:

int doublesize(path** array,int n){
    path* new_array=realloc( *array, n*2*sizeof(path));
    if(new_array==NULL){
        printf("Error allocating memory\n");
        abort();
    }

    *array=new_array;
    return n*2;
}

Call the function by

maxsize=doublesize(&array,maxsize); 

Upvotes: 1

dbush
dbush

Reputation: 224587

The problem is in your resizing function:

int doublesize(path* array,int n){
     ...
     array=new_array;

The variable array is local to the function, so changes to it aren't reflected in the calling function. As a result, array in main now points to freed memory after this function returns, and attempting to dereference that pointer invokes undefined behavior.

You should change this function to accept a path **:

int doublesize(path **array,int n){
    path *new_array=malloc(n*2*sizeof(path));
    if(new_array==NULL){
        printf("Error allocating memory\n");
        abort();
    }

    for(int i=0;i<n;i++){
        new_array[i]=(*array)[i];
    }
    free(*array);
    *array=new_array;
    n*=2;
    return n;

}

And pass the address of array in main:

maxsize=doublesize(&array,maxsize); 

Upvotes: 1

Related Questions