Reputation: 175
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
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
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
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