Reputation: 103
I have a problem in this code, it executes successfully until reach fclose(fp) statement, it crashes.
void read_file(const char *filename) {
FILE *fp;
int num, i=0;
fp = fopen("numbers.txt","r");
if (fp == NULL) {
printf("Couldn't open numbers.txt for reading.\n");
exit(0);
}
int *random = malloc(sizeof(int));
if (random == NULL) {
printf("Error allocating memory!\n");
return;
}
while (fscanf(fp, "%d", &num) > 0) {
random[i] = num;
i++;
}
printf("\nTEST Before close");
fclose(fp);
printf("\nTEST After fclose");
}
The sentence TEST Before close is printed successfully and then the console is stopped printing so TEST After fclose doesn't printed and the cursor start blinking !
Any help? Thanks in advance.
Upvotes: 0
Views: 1987
Reputation: 73366
The problm is that
int *random = malloc(sizeof(int));
only allocates ONE single integer.
If you have more than one integer in your file, your while
will increment i
index and you will write your variable in an invalid location causing memory corruption. This can trigger a segfault, but it can also result in weird behaviour at any time, as in your case.
random[i] = num; /* oops !!! if i>0 memory corruption */
Solutions:
If you know the number
of integers, you can allocate immediately the right amount memory. I recommend calloc()
for this purpose, as it's meant for array allocation, and initializes the allocatied memory to 0:
int *random = calloc(number, sizeof(int));
If you don't know the number you could extend gradually the size of your array, using realloc()
:
int number = 100; /* arbitrary initial size*/
int *random = malloc(number*sizeof(int));
...
while (fscanf(fp, "%d", &num) > 0) {
if (i==number-1) {
number += 100; /* consider allocating 100 more items */
random = realloc (random, number*sizeof(int));
if (random==NULL) {
printf("Not enough momory for reading all the numbers.\n");
exit(1);
}
}
random[i] = num;
i++;
}
A last way to proceed is to infer a maximum number of integers based on the file size:
fseek (fp, 0, SEEK_END); // go to the end
long size=ftell (fp); // get the length of file
fseek (fp, 0, SEEK_SET); // go to start
long number = size/2 + 1; // each number is at least 1 digit folowed by a space, except the las one
if (n > INT_MAX) {
printf("File too big !\n");
exit(1);
}
int *random = calloc((size_t)number, sizeof(int));
...
This is of course practical, but SEEK_END is unfortunately not supported by all library implementations.
Upvotes: 3