need help solving a segmentation fault with file i/o in C - file

I read the input file , which has 911 lines , and want to copy these 911 lines into the output file , after making a few changes to each line..
I am getting segmentation fault when i run this.. I dont know why.. can anyone please help..
#include<stdio.h>
void main()
{
int i;
FILE *fin,*fop;char* str;
fin=fopen("atk561011.txt","r");
if(fin=NULL) printf("ip err");
fop=fopen("svmip.txt","w");
if(fop=NULL) printf("op err");
for(i=1;i<=911;i++)
{
fgets(str,150,fin);
if((i>300&&i<=360)||(i>600&&i<=660))
str[7]='1';
else
str[7]='0';
fputs(str+7,fop);
putc('\n',fop);
}
fclose(fin);
fclose(fop);
}

For a start, this is wrong:
if(fin=NULL)
Should be:
if (fin == NULL)
(the same goes for fop, of course). And if you didn't succeed opening the file - don't just print an error, exit, because what are you going to read from? Keep in mind that the output of printf is buffered and in case of a segfault you won't always see it at all, even if it ran before the fault.
Another thing: you don't allocate memory for str, yet write into it with fgets.
And another thing: reading a pre-defined amount of lines from the file is probably a bad idea. It's better to read from the input until there is an end of file, or until a required amount of lines has been read.

Your not allocating any space for the pointer str.
Change that to either char str[/*Max Length You expect 150? */] or allocate the buffer.
In the meantime your code is walking all over memory - thus the segmentation fault.

Here's the corrected code that should do it.
#include
#define MAX_BUF 150
void main()
{
int i;
FILE *fin,*fop;char* str;
str = malloc((MAX_BUF * sizeof(char)) + 1);
if (str == NULL){
printf("Out of memory\n");
exit(-1);
}
fin=fopen("atk561011.txt","r");
if(fin == NULL){
printf("ip err");
exit(-2);
}
fop=fopen("svmip.txt","w");
if(fop == NULL){
printf("op err");
exit(-3);
}
for(i=1;i<=911;i++)
{
fgets(str,150,fin);
if((i>300&&i<=360)||(i>600&&i<=660))
str[7]='1';
else
str[7]='0';
fputs(str+7,fop);
// What is that for? should it be
// fputs(str, fop); ?????
// since you're outputting the 7'th character (1/0)?
putc('\n',fop);
}
fclose(fin);
fclose(fop);
if (str != NULL) free(str);
}
I have added logic checking to ensure if the file exists, to continue processing. Failure to do so will cause the code to blow up. Since in the original code, you were printing "ip err" if the input failed or in the case of output failure, yet continue on into the for loop which will render the execution to fail in that case as it would still be attempting to read from an non-existant file handle on failure.
Edit: Please see the comment above in the code. Are you trying to output 1/0's based on the conditional value of i between the ranges of 300-360 and 600-660 inclusively, into the output file. Can you clarify? Should that be
fputs(str[7], fop);
Hope this helps,
Best regards,
Tom.

Both fin=NULL and fop=NULL should both be using the 'equal-equal' operator. You're setting fin and fop to NULL instead of checking for a bad return value.

Related

why the program give "Segmentation fault" after 1018 try

I'm writing a C code to open txt file and read two lines on it then print the value
it worked for 1018 time then it gives "Segmentation fault"
I've tried to flush the buffer but it don't work
while(running) {
i = 0;
if ((fptr = fopen("pwm.txt", "r")) == NULL) {
printf("Error! File cannot be opened.");
// Program exits if the file pointer returns NULL.
exit(1);
}
fptr = fopen("pwm.txt","r");
while (fgets(line,sizeof(line), fptr)){
ppp[i]=atoi(line);
i++;
}
fclose(fptr);
printf("%d %d\n",ppp[0],ppp[1]);
rc_servo_send_pulse_us(ch, 2000);
rc_usleep(1000000/frequency_hz);
}
Actually, the file-opening is the likely culprit: On e.g. Linux there's a limit to how many files you can have open, and it typically defaults to 1024. A few files are used for other things, and your program probably uses some other file-handles elsewhere, leaving only around 1018 left over.
So when you open the file twice, you leak the file handle from the first fopen call, and then your second fopen call will fail and give you a NULL pointer in return. And since you don't check for NULL the second time you attempt to use this NULL pointer and have a crash.
Simple solution: Remove the second and unchecked call to fopen.

Trying to read a file line by line in C but the while loop never terminates

My class requires me to write an operating system simulator in C. The first project was to read in two files, a config file and a metadata file. My first attempt at running the finished code led to a segmentation fault (which I believe I solved). Now I'm having an issue with my fgets statement reading line by line. It's reading every line, but it never stops reading lines. It reads through the file indefinitely until I end the process. I put a printf statement in the while loop so I can see what it's reading, and it does go through each line.
int readCfgFile (char *filename, CONFIG *filedata)
{
char buffer[255], trash[255];
FILE *cfgfile = malloc(sizeof cfgfile);
cfgfile = fopen(filename, "r"); // Assumed where segfault was
if(!cfgfile)
{
return -2; // Error opening file
}
char *schedulingCode = malloc(8);
char *logToCode = malloc(200);
char *tempLine; // Suggested to me as a fix (the using a separate variable part)
fgets(trash, 255, cfgfile); //Trash the first line of the file
tempLine = fgets(buffer, 255, cfgfile);
while(tempLine != NULL)
{
sscanf(buffer, "Version/Phase: %d", &filedata->version);
sscanf(buffer, "File Path: %s", filedata->metaPath);
sscanf(buffer, "CPU Scheduling Code: %s", schedulingCode);
sscanf(buffer, "Quantum Time (cycles): %d", &filedata->quantum);
sscanf(buffer, "Memory Available (KB): %d", &filedata->memory);
sscanf(buffer, "Processor Cycle Time (msec): %d", &filedata->processTime);
sscanf(buffer, "I/O Cycle Time (msec): %d", &filedata->ioTime);
sscanf(buffer, "Log To: %s", logToCode);
sscanf(buffer, "Log File Path: %s", filedata->logPath);
tempLine = fgets(buffer, 255, cfgfile);
if(tempLine == NULL)
{
break;
}
printf("%s\n", buffer);
}
The file looks like this:
Start Simulator Configuration File
Version/Phase: 1.0
File Path: Test_3.mdf
CPU Scheduling Code: NONE
Quantum Time (cycles): 55
Memory Available (KB): 667
Processor Cycle Time (msec): 10
I/O Cycle Time (msec): 20
Log To: Monitor
Log File Path: logfile_1.lgf
End Simulator Configuration File.
Does anyone have any idea why the while loop keeps going on forever?
When you say the loop runs forever do you keep getting some output for the statement printf("%s\n", buffer); just before the loop termination. Is so what's being printed?
I'd suggest to test the loop logic independent of sscanf code. Following block should work as such (do not need extra check etc.)
fgets(buffer, 255, cfgfile); // just to skip the first line
while( (tempLine = fgets(buffer, 255, cfgfile)) != NULL)
{
// all the scanfs to read from tempLine/buffer
..
}
With that in place you may want to add in your sscanfs and progressively go from there. Some minor comments around FILE *cfgfile = malloc(sizeof cfgfile);. This is not required because the call to fopen will return a pointer to FILE and you'll end up leaking the malloc'd cfgfile. Also not sure if this is the complete code or not but logToCode and schedulingCode will also end up getting leaked.
Welcome to SO! Note that you really need an MCVE for questions like this... Also, do not update your question to change the code; this changes the question, which renders all previous answers to it invalid. If you're going to ask a new question, ask it as a new question!
char *tempLine = malloc(sizeof tempLine); // Suggested to me as a fix
I don't trust that fix. Why allocate a block of memory pointing at a char, that has the size of a char *? How unusual... There are several other variables in your code that are initialised like this, and it seems like guess-work. Your guess-work is likely causing problems.
tempLine = fgets(buffer, 255, cfgfile); then overwrites the pointer to that allocation with buffer or NULL, which results in a memory leak. Whoever suggested that fix to you needs to learn about valgrind (as do you).
Nonetheless, if you ever wish to trash a line of input, that'd be better achieved without an intermediate buffer like so:
fscanf(cfgfile, "%*[^\n]");
fgetc(cfgfile);
I'm curious, why is it you appear to be using %d to read floating point data?
sscanf(buffer, "Version/Phase: %d", ... // Version/Phase: 1.0
If only I could see the type of filedata->version, I might be able to verify this as an error...
You claimed to have updated this code, yet I can't see the update:
tempLine = fgets(buffer, 255, cfgfile);
if(buffer == NULL) // Even checking to see if buffer was null doesn't work
There's an error here, and to identify it, I want you to show me how fgets could assign buffer = NULL; like you seem to expect, in this testcase:
#include <stdio.h>
char *fgets_fake(char *b, int b_length, FILE *f) {
/* INSERT CODE HERE! */
/* Show me how `fgets` can assign `buffer = NULL;` here */
return b;
}
int main(void) {
char *buffer = "HELLO WORLD!";
fgets_fake(buffer, 0, 0);
printf("Is buffer NULL? %s\n", b ? "no" : "yes");
}
You probably meant if (tempLine == NULL), since that can be reassigned (following the return).

segmentation fault in file handling

int main()
{
FILE *f;
f=fopen("words.txt","r");
char wd[10];
string word;
printf("Enter a word to be searched\n");
word=GetString();
while (!feof(f))
{
fscanf(f,"%s",wd);
//printf("%s\n",wd);
if(strcmp(word,wd)==0)
{
printf("Yes\n");
break;
}
}
fclose(f);
return 0;
}
If the word to be searched, is present in the file, it is giving the correct answer- YES, otherwise, its giving segmentation fault(core dumped).
Please help!!
Line 6: string word;
There is no string data type in C. And,
Line 8: word = GetString();
You didn't include definition of function. Assuming it returns pointer to a string, but won't work anyway because line 6 will not compile.
Use: char word[10] if your sure word won't be longer than 9 characters.
#gnometorule was correct. You're reading one more time than you need to. If you checked your return value, you would find fscanf probably returned EOF. What you want to do is read the file as long as fscanf returns an expected value. Since you are reading 1 item, it should return 1. If it doesn't, there is a problem. Moreover, feof will only be true if the end of the file was reached. What if there was a read error? You may be trying to read from a file that has its error indicator set, and feof won't detect that.
Review the following code. It should give you an idea of how to handle files.
/* This is used to determine whether an end-of-file error message should be printed or the word was found. */
int cmp_result;
/* Stop reading when the file can't be read or the words are equal. */
do
cmp_result = strcmp(word, wd);
while (fscanf(f, "%s", wd) == 1 && cmp_result != 0);
/* Check for a file read error. */
if (ferror(f))
printf("Error reading file\n");
/* End of file reached before words are equal; feof(f) may be true when cmp_result==0 or not, so checking cmp_result is more reliable in this case. */
else if (cmp_result != 0)
printf("Word '%s' not found\n", word);
/* Words are equal. */
else
printf("Yes\n");
The logic is that if the loop was exited, there was a read error or the word was found. The branching statements after the loop test this.
First, the file's error indicator is checked. If it isn't set, the end of the file was reached, or the word was found.
If the word was found, the end of file indicator may be set or not. But if the word wasn't found, the end of file indicator must be set, else the loop wouldn't have exited since we already ruled out the error indicator in the first if statement. This is why we check the comparison result instead of using feof(f).
If those cases fail, we are left with one possibility: the word was found.
I hope this helps!
Anytime while (!feof(f)) is in your code, it almost means that you are in the wrong place. feof() will only be set after reading the end of the stream. It does not indicate, that the next read will be the end of the stream. See here for more info.
Replace
while (!feof(f))
{
fscanf(f,"%s",wd);
... ...
}
by
while (fscanf(f,"%s",wd))
{
... ...
}

C - Reading File Error.. !f_in is null and dont know why?

// Trying to read file
void readFilee(char *namefile){
FILE *f_in = fopen(namefile,"r");
char x;
int i = 0;
if(!f_in){ printf("Error"); exit(0); }
/* read to EOF */
while(1){
x = getc(f_in);
if(x == '\n') continue;
archivo[i] = x;
if(x == EOF) break;
i++;
}
tamArchivo = i;
fclose(f_in);
}
Fact that the error was f_in is null, but I do not understand why? I'm trying to connect a server with multiple clients, the clients are initialized waiting connection.
The command verificion "if" I get "Error"
add
archivo[i] = '\0';
after the while loop terminate. This will add null charachter at the end of your string archivo
also may be the memory space of your archivo array is not sufficient to get the whole content of the file and so it could cause a buffer overflow so it could cause a crash
Verify f_in is not NULL before using it. I bet fopen fails and this causes f_in to be NULL. Later when you call getc, it will crash.
If that is not the case, try debugging your application with cgdb for instance and see which line causes the crash.
Try replacing while (1) with while (!feof(f_in)). This will exit the loop when the file is at the end. You shouldn't check for end of file like you are in your loop. This would require the end of file character to be somewhere in your file. The value of EOF is actually specifically designed so it doesn't appear in your files.
Other things to look at are uncommenting your check that the file was opened successfully. If this check is failing then you shouldn't attempt to use any of the fxxx functions on the file pointer.
you are not checking for array boundaries of "archivo"
that'd be for me the first thing to check

Reading a C file, read an extra line, why?

I don't know exactly why a file pointer reads an extra line from a file, specifically the last line, here is the code:
FILE *fp ;
fp = fopen ("mac_ip.txt", "r") ;
int mac;
char *ip = (char *) malloc(15);
while(!feof(fp)){
fscanf(fp,"%i",&mac);
fscanf(fp,"%s",ip);
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
and the file has exactly 20 lines, but the line 20, is printed twice.
Which is the error?
Thanks in advance.
Because after reading the last two values, you still haven't hit EOF. So the loop goes on. In the next pass of the loop, fscanf actually does not read the last line for the second time like it appears, the fscanfs fail, but the printfs print out the values from the previous pass of the loop.
feof does not "know" it's at the end of file until you try to read some more. Since fscanf tells you how many items it got, you can use this simple trick:
for(;;){
if (fscanf(fp,"%i%s", &mac, ip) != 2) break;
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
After you have done the two reads on the twentieth line, you have got to the end of the file but the system doesn't know this. feof will only trigger when you try to get past the end of the file, not when you are exactly on it ...
Also, you may have a line-end (CR or CR-LF) on the 20th line which it will only get past with another attempted read.
The solution is to read the line in one go (there is a specific C command for this) and then parse that to get your data. If the whole-line read fails, then you've got to the end.
Your code resembles to the following example
#include <stdio.h>
int main(void)
{
char buffer[256];
FILE * myfile;
myfile = fopen("some.txt","r");
while (!feof(myfile))
{
fgets(buffer,256,myfile);
printf("%s",buffer);
}
fclose(myfile);
return 0;
}
from
http://www.friedspace.com/feof.html
You better test for fscanf return value before printing result. I bet that in the last iteration of your loop, fscanf calls fail and you print the last returned results.
FILE *fp ;
int mac;
char ip[15];
fp = fopen ("mac_ip.txt", "r") ;
if (!fp) return;
while(1){
if (fscanf(fp,"%i",&mac) < 1) break;
if (fscanf(fp,"%s",ip) < 1) break;
printf("MAC: %i\n",mac);
printf("IP: %s\n",ip);
}
fclose (fp);
fscanf() returns the number of assignments it mad (or -1 on eof). By using the return value, you don't need the eof() function. BTW I don't think you can read a MAC address into an int. Maybe you need to read that into a string, too ?
Explanation: feof() does not do what the OP expects. feof() should only be inspected after one of the file operations failed. In most cases you don't need feof().

Resources