Click to See Complete Forum and Search --> : Segfault reading from file


boy_wonder
10-10-2000, 10:30 AM
I don't know much about C, but am trying to write a log file analyser. But when I try to read from a file I get a segfault.

I will try and only put the relevant pieces of code in

fgetpos(log,pos);
while ((ch=fgetc(log))!=' ') {
count++;
}
fsetpos(log,ppos);
user=(char *)malloc(count+1);
ch=fgetc(log);

It doesn't matter what I have on that last line. If it reads from the file it Seg faults. I have an almost identicle bit of code else where that works fine. I must be missing something.

Please help.
Thankyou in advance.

TheLinuxDuck
10-10-2000, 11:18 AM
That code snippet doesn't give enough of a clue as to what you're trying to do, and what the code is doing. http://www.linuxnewbie.org/ubb/smile.gif It *looks* like you're counting all the non space chars in a file.

In the fsetpos, are you meaning to move the position to ppos or pos?

You might post more of the code, or detail what you are trying to accomplish through what steps.. http://www.linuxnewbie.org/ubb/wink.gif

------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq

Strike
10-10-2000, 01:17 PM
throw an OR'ed conditional into your while that checks for an EOF somehow (I don't know how to with C streams, though I do for C++ streams). Basically, your loop will continue running off past the end of the file under certain conditions. Now, I'm not sure if this is what is causing your error, but it's possible.

TheLinuxDuck
10-10-2000, 02:38 PM
Originally posted by Strike:
throw an OR'ed conditional into your while that checks for an EOF somehow (I don't know how to with C streams, though I do for C++ streams).


while(!feof(fstream)) {
if((ch=fgetc(fstream))!=EOF) {
dostuff(ch);
}
}


Strike, will you post an example of the C++ stream check? I am curious to see the difference. http://www.linuxnewbie.org/ubb/smile.gif

------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq

Strike
10-10-2000, 03:46 PM
Okay, here goes the whole thing in C++ (because declarations and stuff would be different).

#include <fstream>

int main (int argc, char* argv[])
{
if (argc !=2)
{
cout << "Usage: strip-whitespace <filename>" << endl;
return 1;
}

fstream file(argv[1], ios::in);
if (!file)
{
cout << "Problems handling file " << argv[1] << endl;
return 1;
}


// Get the filesize so we don't go past that
file.seekg(0, ios::end);
int SizeOfFile = file.tellg();

file.seekg(0, ios::beg); // put us back at byte 0

int CurrentByte;
int count=0;
char temp_char;
// Main loop starts here
while (CurrentByte < SizeOfFile)
{
file.get(temp_char);
CurrentByte++;

if (temp_char = ' ')
count++;
}

file.close();
return 0;
}

I think this works... let me test it.

---edit---
1. minor fix
2. duh, fixed not initializing count

[This message has been edited by Strike (edited 10 October 2000).]

Strike
10-10-2000, 03:56 PM
Hmmm... doesn't quite work. First of all, that code doesn't do anything meaningful since it doesn't report back the number of non-whitespace characters (and I now realize the faux name in the "Usage:" block is just way off and that it should be something like "count-non-space"). But, even if you add that in, it's still not working quite right. Oh well, that sets up the file stuff right, I'm pretty sure. I think I might need to move the get pointer after doing a get.

TheLinuxDuck
10-10-2000, 04:01 PM
Qool, dood... http://www.linuxnewbie.org/ubb/smile.gif I've never actually seen or done file io in c++ yet. http://www.linuxnewbie.org/ubb/smile.gif

Btw, shouldn't:

if (temp_char = ' ')
count++;

be

if (temp_char == ' ')
count++;

???

Thanks for posting this, by the way.
Do you mind if I steal it and add comments to it and use it with the Cataloged Collection of Annotated Examples, that kmj and I are starting?

If you want to do it, or don't want it used , just let me know.

The VERY SIMPLE beginnings of the CCAE is here: http://www.geocities.com/bfkester/ccae.html

Not much there yet. http://www.linuxnewbie.org/ubb/smile.gif

Thanks again, btw! http://www.linuxnewbie.org/ubb/smile.gif

------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq

Strike
10-10-2000, 09:15 PM
Yeah, maybe that's why it wasn't working. Don't post it yet, because as is, it doesn't work. If you compile it and it works (make sure to change the "Usage: ..." string), then I'll see. But as for now, I'm in Windows (gotta have my Counterstrike), so I'll get back to ya on it.

TheLinuxDuck
10-10-2000, 09:50 PM
Originally posted by Strike:
Yeah, maybe that's why it wasn't working. Don't post it yet, because as is, it doesn't work. If you compile it and it works (make sure to change the "Usage: ..." string), then I'll see. But as for now, I'm in Windows (gotta have my Counterstrike), so I'll get back to ya on it.

After changing the = to == (and changing the usage string to display argv[0], etc) it worked fine.

http://www.linuxnewbie.org/ubb/smile.gif Actually, I have a confession to make. After I asked you about that, I went ahead and modified the code a little, and added comments. I changed it so that it would take a CL list of files and return their file sizes. I also converted it to C, and perl. http://www.linuxnewbie.org/ubb/smile.gif

I was hoping you wouldn't mind. I will post them all tomorrow at work on the CCAE site and let you know, if that's qool wiff youse.

------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq

Strike
10-10-2000, 10:44 PM
Okay http://www.linuxnewbie.org/ubb/smile.gif Glad it worked. If you are sure it's in working order, go ahead and add it to your little compendium of examples and if you are keeping track of authorship, put yourself as co-author for fixing it up for me http://www.linuxnewbie.org/ubb/smile.gif

boy_wonder
10-11-2000, 01:05 AM
Ok here is some more info.
It is part of a program that will eventually add up internet usage on a per user basis. This is from a squid log file. There are different charging rates for australian and internation files.
Each line in the log file looks like:
%9d.%03d %6d %s (%s)/%03d (%d) %s (%s) (%s) %s/%s %s
I am only concerned with the ones in brackets.
The small bit of code I gave moves the file pointer to the start of the last string field I need. There is probably a better way to do it, but I am not worried about that for the time being. I use fgetpos to get the current location in the file, and count the number of characters in the string (which happens to be a user name). I malloc the space +1 for '\0'. And use fsetpos to go back to the start of the string.
ALL WORKS WELL UNTIL THIS POINT.
Then if I try to read from the file I get a Seg fault.

The only reason I can think is that something went wrong with the fgetpos/fsetpos. The code I have on the first post is only a very small piece of the whole program. I used the same method to get the string before hand (which was a url).
the ch=fgetc(log); is a debugging line.

Here is a more readible version. I am typing this in so it might have mistakes. IE = instead of ==. etc


count=0; /* get url */
/* remove white space */
while ((ch=fgetc(log))==' ') {}
ungetc(ch,log);
/* count space for malloc */
fgetpos(log,pos);
while ((ch=fgetc(log))!=' ' ) {
count++;
}
fsetpos(log,pos);
url=(char *) malloc(count+1);
for (i=0;i<count;i++) {
/* will change to fscanf*/
url[i]=fgetc(log);
}
url[count]='\0';
/* check url is another function that
/ returns 0 for international urls
/ and 1 for australian and -1 for an
/ error*/
info->flag=checkurl(url);
printf("Url done\n");
free(url);
if (info->flag == -1) {
info->code =-1;
return info;
}
else {info->flag = 0; }

/* all fine up to this point */

printf("Getting user name\n");
/* get auth user name */
count=0;
/* remove white space */
while ((ch=fgetc(log))==' ') {}
ungetc(ch,log);
fgetpos(log,pos);
/* count size for malloc */
while ((ch=fgetc(log))!=' ' ) {
count++;
}
fsetpos(log,pos);
user=(char *) malloc(count+1);
printf("Space malloced\n");
ch=fgetc(log);
printf("I don't get here");

The fgetc raises the segfault. I have tried fscanf as well and that doesn't work.

boy_wonder
10-11-2000, 01:08 AM
Hey, I just realised that I am a grasshopper. How did that ever happen?

boy_wonder
10-11-2000, 01:40 AM
I fixed it. It is now seg faulting somewhere else. I don't know how or why. I must have done something wrong and fixed it, but I don't know what.
Thank's for the help.

TheLinuxDuck
10-11-2000, 11:31 AM
Originally posted by boy_wonder:
I fixed it. It is now seg faulting somewhere else. I don't know how or why. I must have done something wrong and fixed it, but I don't know what.
Thank's for the help.

I am curious as to the choice of using fgetpos/fsetpos. The code is parsing the log file line by line right?

Could the code not skip all the file position jumping by reading in each line with fgets, and parsing the string, something like:


char tempbuffer[255];
while(!feof(fptr)) {
if((fgets(tempbuffer,255,fptr))!=NULL)
parsestringfunction(tempbuffer);
}


I realize that this is simplified, but if the code is going to read the file line by line, why not make it easy on yourself?

I noticed that the code is not doing any error checking, in the example listed, for malloc, to make sure that it is actually allocating the space. This can cause problems. http://www.linuxnewbie.org/ubb/smile.gif

I'll take a little more time today looking at it, and see if I can think of anything else that might be causing troubles.

------------------
TheLinuxDuck
Wait... that's a penguin?!?!?
:wq

boy_wonder
10-12-2000, 03:49 AM
The reason for the fsetpos/fgetpos is to work out the amount of space I need to malloc for the string.
I am thinking of modifying it for a hopeful performance increase by just getting a character and writing it out to the output file.

Yes I should probably check what malloc returns. Don't bother taking too much time looking at it. That was only a small part that I have written so far and am will not be able to modify it for the next two weeks due to too much uni work.

Thanks for the help