Segmention Fault while in the middle of nested for loop - c

I've written a code that needs to read in a series of values from a user specified data file (This could be up to 10,000 rows of data) which is done in the first for loop. In each row of values one of the variables is converted to a string which defines another set of input files(each containing ~20,000 rows of data) to load which are needed in the second for loop for calculations. This works well for the first few hundred iterations... it reads in everything correctly, and the resulting calculations (Calculations are omitted in the code below because the code produces the same problme with or without them) are as expected.
The problem is that when the first for loop reaches around 600 iterations it stops and produces the error: segmentation fault(core dumped)
I'm pretty sure this is a memory problem of some sort because if I've tested the code by omitting 4 of the input files in the second loop and it's capable of reaching a higher number of iterations....
This is the code:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int main()
{
int num, i, j;
double X, Y;//
float Z;
char the_data[25], Z_name[10], input_1[50], input_2[50], input_3[50], input_4[50], input_5[50];
double a, b, c, d, e;
printf("Enter the name of the data file you are using:\n");
scanf("%24s", &the_data);
FILE *DATA = fopen(the_data,"r");
for (j=1; j<800; j++)
{
//***************Read data from a file, the variable Z is a floating point number which, when rounded to the nearest decimal place,
//********************determines which directory to load model data from for each value of X and Y
fscanf(DATA, "%lf %lf %f\n", &X, &Y, &Z);
//round Z to the nearest 1 decimal place
Z = Z * 10;
Z = roundf(Z);
Z = Z / 10;
//assign the full directory name to Z_name
sprintf(Z_name, "%.01fdirectory", Z);
//assign Z_name to input name string for path to the appropriate data file locations
sprintf(input_1, "./%s/a.txt", Z_name);
sprintf(input_2, "./%s/b.txt", Z_name);
sprintf(input_3, "./%s/c.txt", Z_name);
sprintf(input_4, "./%s/d.txt", Z_name);
sprintf(input_5, "./%s/e.txt", Z_name);
//Open the files
FILE *input1 = fopen(input_1, "r");
FILE *input2 = fopen(input_2, "r");
FILE *input3 = fopen(input_3, "r");
FILE *input4 = fopen(input_4, "r");
FILE *input5 = fopen(input_5, "r");
for (i=1; i < 10000; i++)
{
//For a given Z value, read in the corresponding values. Usually these input files have ~20000 values in each so the loop would be set to run until the end of the file
fscanf(input1, "%lf", &a);
fscanf(input2, "%lf", &b);
fscanf(input3, "%lf", &c);
fscanf(input4, "%lf", &d);
fscanf(input5, "%lf", &e);
}
//Test to see how far it gets in loop before giving up due to segmentation fault
printf("The iteration number is: %d\n", j);
}
printf("This will print if the program reaches the end of the first loop\n");
}
I'd appreciate any tips or pointers in dealing with this problem. Thanks!

You need to check the return value from fopen(). Since you're never closing the input files, you're probably hitting the limit on open files. Then fopen() returns NULL, and when you try to use that with fscanf() you get a segfault.
//Open the files
FILE *input1 = fopen(input_1, "r");
if (!input1) {
printf("open input_1 failed\n");
exit(1);
}
FILE *input2 = fopen(input_2, "r");
if (!input2) {
printf("open input_2 failed\n");
exit(1);
}
FILE *input3 = fopen(input_3, "r");
if (!input3) {
printf("open input_3 failed\n");
exit(1);
}
FILE *input4 = fopen(input_4, "r");
if (!input4) {
printf("open input_4 failed\n");
exit(1);
}
FILE *input5 = fopen(input_5, "r");
if (!input5) {
printf("open input_5 failed\n");
exit(1);
}
for (i=1; i < 10000; i++)
{
//For a given Z value, read in the corresponding values. Usually these input files have ~20000 values in each so the loop would be set to run until the end of the file
fscanf(input1, "%lf", &a);
fscanf(input2, "%lf", &b);
fscanf(input3, "%lf", &c);
fscanf(input4, "%lf", &d);
fscanf(input5, "%lf", &e);
}
//Test to see how far it gets in loop before giving up due to segmentation fault
printf("The iteration number is: %d\n", j);
fclose(input1);
fclose(input2);
fclose(input3);
fclose(input4);
fclose(input5);

Related

Why am I getting this segmentation fault in my code while iterating through large quantities of int values?

The C program I am trying to write is meant to take a file of integer values and sum the first number with the second, then the first with the third, the first with the forth, and so on. Then sum the second with the third, the second with the forth, and so on. It is also meant to print a message whenever a predetermined value is met while adding all the numbers (in my case, it's 10), and print out the time it took for this program to execute.
However, when the program starts going through the list of integers in the file I am taking values from (over 10,000 integers are in this file), it seems that it gets to the 124th loop and then gives me a Segmentation Fault (Core Dumped) error. When I reduce the number of integers to be added to under 124, the program works fine.
Why am I getting this Segmentation Fault error? Is it in the way that I set up my While loops? Is there any way I can remedy this?
#include<stdio.h>
#include <time.h>
int main(){
FILE *fptr1,*fptr2,*temp;
fptr1 = fopen("input.txt", "r") ;
int num1,num2;
int sum=0;
int c=0;
if (fptr1 == NULL) {
printf("File not open\n");
return 0;;
}
int count=0;
clock_t t;
t = clock();
// the problem seems to be in this while loop//
while(fscanf(fptr1, "%d", &num1) !=EOF){
count++;
fptr2 = fopen("input.txt", "r") ;
int count1=0;
while(fscanf(fptr2, "%d", &num2) !=EOF){
count1++;
if(count1>count){
sum=num1+num2;
if(sum==10){c++;}
}
}
}
printf("sum of 10 was found in %d iterations of loop",c);
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
printf("Time taken :%lf", time_taken);
fclose(fptr1);
fclose(fptr2);
return 0;
}
When the file has over 124 integers, it gives me this:
the output when over 124 integers
and when he file has less than 124 integers, it gives me this:
the output when under 124 integers
The problem seems to be opening way too many file handles, but the fix should be simple:
while(fscanf(fptr1, "%d", &num1) !=EOF){
count++;
// This fopen() call might fail, you should check the result
fptr2 = fopen("input.txt", "r");
int count1 = 0;
while(fscanf(fptr2, "%d", &num2) != EOF) {
// ...
}
// If you open a file, you must close it before re-opening
fclose(fptr2);
}
This is quite wasteful, though, there's no reason to open over and over, instead
just rewind the file and use it again:
fptr2 = fopen("input.txt", "r");
while(fscanf(fptr1, "%d", &num1) !=EOF) {
// Move back to the beginning of the file before reading
rewind(fptr2);
count++;
int count1 = 0;
while(fscanf(fptr2, "%d", &num2) != EOF) {
// ...
}
}
fclose(fptr2);
Another thing to note here is your variable names are extremely opaque. fptr2 doesn't communicate anything about what this is supposed to be used for, or what that file might contain. If it correlates with an input source, consider input or finput or even fin. Likewise, count1 and count and an even more mysterious c are confusing. Counting what? For what reason?

Read Values from a file and store it in 2D matrix

I am trying to read values from a file and after some operation write to another file. Here facing a slight issue as I am also trying to save values in a 2D Array and displaying it. My file read and file write are showing correct results but my program throws an exception when it comes to display matrix part.
#include <stdio.h>
#include <ctype.h>
#ifndef NULL
#define NULL ((void *) 0)
#endif
int main(void)
{
FILE *file = NULL; //for file read
FILE *fptr = NULL; //for file write
int mat[182][274];
// code to read and display number from file
// open file for reading
file = fopen("file.txt", "r");
fptr = fopen("file1.txt", "w");
int i = 0,j=0;
fscanf (file, "%d", &i);
while (!feof (file))
{
symbol = fgetc(file);
if (symbol == '\n' || feof(file))
{
fprintf (fptr,"\n");
printf("\n");
}
else{
j=255-i;
mat[i][j]=j;
fprintf (fptr,"%d ", j);
fprintf (fptr," ");
printf ("%d ", j);
}
fscanf (file, "%d", &i);
}
fclose (file);
fclose (fptr);
//Facing issue in this part
int k;
int l;
for (k=0;k<=182;k++)
{
for(l=0;l<=274;l++)
{
printf("%d ", mat[k][l]);
}
}
return 0;
}
Arrays in C start at 0 and end at (array_size - 1).
As you're accessing memory just outside the array, you're most likely experiencing segmentation faults.
To fix this issue, change these lines:
for (k=0;k<182;k++)
{
for(l=0;l<274;l++)
{
printf("%d ", mat[k][l]);
}
}
Notice that I changed the relational operators from <= and >= to < and >, respectively.
Along with that, you may need to fully initialize your array. Odd values may be printed if the array is not initialized. (#Weather Vane).
However, to best be sure if this is the case, we need file.txt and file1.txt.

C: rewind() segmentation faults on 252nd attempt

I am writing some code that inputs grid coordinates of "islands" (connected points on a grid) and finds the center of mass for each island. The code is successful for grids with a few large islands, however, it fails for grids with many small islands.
I've narrowed down the issue to rewind() failing on the 252nd loop-through. I have no idea why it fails as I've verified that island # 252 exists by printing the coordinates prior, and if I skip 252, the code fails on island 253, so I believe it is just rewind failing after 252 uses.
The code is quite large, so I'll try to just post the relevant parts:
FILE *f;
if((f = fopen(argv[1], "r")) == NULL)
{
printf("Could not open file to read.\n");
return 0;
}
while(!feof(f))
{
fscanf(f, "%d %d %d\n", &current_x, &current_y, &island_number);
if(island_number > number_of_islands)
{
number_of_islands = island_number;
}
}
fclose(f);
This the first instance when f is used, but it's used again later, and again in the following for loop which is where the problem emerges:
for( int i = 0; i < number_of_islands; i++)
{
printf("new loop: %d (number of islands: %d) \n", loop, number_of_islands);
if(loop == 252)
{
printf("putting in x, y at 252...\n");
}
This is where the code fails...
//putting numbers in x and y
rewind(f = fopen(argv[1], "r"));
Here's a bit of the following part (probably not important):
if(loop == 252)
{
printf("rewound at 252...\n");
exit(0);
}
while(!feof(f))
{
fscanf(f, "%d %d %d\n", &current_x, &current_y, &island_number);
if(island_number == current_island_number)
{
x_array[current_x] += 1;
y_array[current_y] += 1;
}
}
if(loop == 252)
{
printf("finished putting in x, y at 252...\n");
exit(0);
}
A sample of what the output looks like is this:
Everything looks good, except for the sudden segfault.
So my question is, why is rewind() suddenly segfaulting on the 252nd attempt?
this: rewind(f = fopen(argv[1], "r"));
does not rewind f.
instead it assigns a new value for f, opening the same file and rewinding it (although it has just been opened).
on some systems there is a limit to the open file descriptors you can have. why 252? i guess your limit is 256 and the kernel probably uses the remaining 4.
to fix the problem you can either close the file first, or:
rewind(f);
this should work with no reassignment of f.

Can't read a single double value from a file (C)

I am having trouble reading in just a single data point from a file. It is supposed to be able to read two columns of data (such as x and y values), but I found out my code cannot even read a single value of double precision. Any help would be appreciated.
The file is at D:\test.txt
and there is a single value of 1.11111.
Enter the location of file (text file) of the airfoil coordinates: D:\test.txt
There are 1 lines
The amount of data in x and y is 1 points and 1 points.
failed to read.
* Process returned 1 *
Press any key to continue...
That was my input.
/*
Purpose:
Create a program that can take in a list of data points that represents an airfoil from some file.
Then through the use of spline function, spline the data points for interpolation then go on to plotting them.
With these data points, use the Vortex Panel Method to obtain coefficients of lift, pressure, and tangential velocity.
Then after these are calculated, plot each with respect to the splined x data points.
*/
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#define LEN 12
int countlines(FILE *fp);
int main (void)
{
char airfoil[500];
double *x_data = NULL;
double *y_data = NULL;
FILE *pfile = NULL;
int line_count = 0;
double test = 0.0;
printf("Enter the location of file (text file) of the airfoil coordinates: ");
scanf("%s", airfoil);
if(fopen_s(&pfile, airfoil, "r"))
{
printf("Error opening the file for reading the data. Program terminated.\n");
exit(1);
}
line_count = countlines(pfile);
printf("There are %d lines\n", line_count);
x_data = realloc(x_data, line_count*(sizeof(double)));
y_data = realloc(y_data, line_count*(sizeof(double)));
if((!x_data) || (!y_data))
{
printf("Memory allocation has failed. Exiting...\n");
exit(1);
}
printf("The amount of data in x and y is %zu points and %zu points.\n", (sizeof(x_data)/sizeof(double)), (sizeof(y_data)/sizeof(double)));
if(EOF == fscanf_s(pfile, "%lf", &test))
{
printf("failed to read.\n");
exit(1);
}
//for(int i = 0; i < line_count; i++)
//{
//fscanf(pfile, " %lf", &x_data[i]);
//}
printf("The x-data are %lf!\n", test);
//for(int i = 0; i < line_count; i++)
//{
//printf("%.2lf", x_data[i]);
//printf("\n");
//}
return 0;
}
int countlines(FILE *fp)
{
int lines = 0;
char str[LEN];
while(!feof(fp))
{
if (fgets(str, LEN, fp) != NULL);
{
lines++;
}
}
return lines;
}
countlines just brought the file pointer to the end of file. Before you can read anything, you must first rewind the file to the beginning:
fseek(pfile,0,SEEK_SET);
You can do ths in countlines().
See also the comments, that spot some more errors.

How to Read and Write integers to a file

The thing is that im trying to read some integers to know the levels of the game I have already passed through, then I want to put the integer of the current level to one if t is not already. It creates the file but doesn't write anything. Anyone know why? Now, it does it the first time when creating it with printf but when reading it gives status access violation.
void SaveGame(void)
{
FILE *pFile = fopen("SavedData.txt","rb");
int MyArray[8] = {0};
if(pFile)
{
fscanf(pFile, "%d %d %d %d %d %d %d %d" , MyArray[0], MyArray[1], MyArray[2], MyArray[3], MyArray[4], MyArray[5], MyArray[6], MyArray[7]);
fclose(pFile);
}
if(MyArray[Current] == 0)
MyArray[Current] = 1;
pFile = fopen("SavedData.txt", "wb");
if(pFile)
{
fprintf(pFile, "%d %d %d %d %d %d %d %d" , MyArray[0], MyArray[1], MyArray[2], MyArray[3], MyArray[4], MyArray[5], MyArray[6], MyArray[7]);
fclose(pFile);
}
}
You can do what you want something like this (untested) :
#define SAVE_FILE "SavedData.txt"
#define NUMS_SIZE 8
void SaveGame() {
FILE *f;
f = fopen(SAVE_FILE, "r");
if (!f) {
fprintf(stderr, "Error: Can't open save file for reading.\n");
exit(-1);
}
int nums[NUMS_SIZE] = {0};
int n, i = 0;
while (fscanf(f, "%d", &n) == 1) {
if (i >= NUMS_SIZE) break;
nums[i++] = n;
}
fclose(f);
f = fopen(SAVE_FILE, "w");
if (!f) {
fprintf(stderr, "Error: Can't open save file for writing.\n");
exit(-1);
}
int j = 0;
if (i > 0) fprintf("%d", nums[0]);
for (j = 1; j < i; ++j)
fprintf(" %d", nums[j]);
fclose(f);
}
That's not how you read a file.
For starters if it is a text file, open with mode "r", not "rb".
When you do a read operation you should check to see whether the read operation suceeded or failed. You don't do feof instead. There is a lot of code out there that does feof and most of it is wrong. Be wary when copying off internet code samples.
Also, it's a great idea to read the documentation for any standard function you use. You may learn things about the function that you didn't know. For example, fscanf returns how many items were successfully read.
So in your reading loop, either check that fscanf returns 8 (or loop 8 times as ooga suggested, checking for 1 each time). Don't check feof during the loop.
Once the read fails, THEN you have the option to do feof to find out why the read failed, if you care to know. It could have fail because you hit the end of file (feof), or because of a device error (ferror), or because the file had words in it instead of numbers.
When you do the writing part, make sure you only write numbers which were successfully read.

Resources