I am currently working on a simple server implemented in C.
Processing jpg files works fine, btu png's give me a segmentation fault. I never get past this chunk of code. Why this might be?
fseek (file , 0 , SEEK_END);
lSize = ftell (file);
rewind (file);
Thanks.
It's far more likely that you were accessing those arrays in a problematic fashion. Check the logic in your buffering code. Make sure you have your buffer sizes #define'd in a central location, rather than hardcoding sizes and offsets. You made it quit crashing, but if you missed an underlying logic error, you may run into mysterious problems down the road when you change something else. It is probably worth your time to deliberately break the program again and figure out WHY it's broken. As others have suggested, a debugger would be an excellent idea at this point. Or post a more complete example of your code.
Related
First off I need to say it's completely possible I'm missing something.
My assignment is to essentially implement 'fprintf'. Now while appending to the file isn't required, I like to go above and beyond.
My issue is, I can't find a definition for lseek in xv6, meaning I have to implement it on my own, but I genuinely don't know how to go about it.
Tried reading 512 bytes at a time on an infinite loop in attempt to move the cursor over to the end, as a way to hardcode it, but if the file isn't opened with O_RDWR or I try this with stdout it fails.
I've also tried writing an empty string on an infinite loop. Knew it wouldn't work, but tried anyways.
I can read xv6 fairly well (The user level programs), but I can't understand the source code of lseek for the life of me
It doesn't have to be a genuine lseek. I just need to be able to get to the end of an fd and continue writing, but this cannot be reliant on filemode.
Any help is greatly appreciated.
I found the solution.
The reason O_APPEND doesn't work is because the definition of open(), in sysfile.c, doesn't do anything with append.
In sys_open, they hardcode a value of 0 for f->off (offset), and this is what I need to change.
My planned solution is to figure out the filesize (in bytes) of the file, and set the offset to that number.
Probably gonna use stat().
I have a long C code. At the beginning I open two files and write something on them:
ffitness_data = fopen("fitness_data.txt","w");
if( ffitness_data == NULL){
printf("Impossible to open the fitness data file\n");
exit(1);
}else{
fprintf(ffitness_data,"#This file contains all the data that are function of fitness.\n");
fprintf(ffitness_data,"#Columns: f,<p>(f),<l>(f).\n\n");
}
fmeme_data = fopen("meme_data.txt","w");
if( fmeme_data == NULL){
printf("Impossible to open the meme data file\n");
exit(1);
}else{
fprintf(fmeme_data,"#This file contains all the data relative to memes.\n");
fprintf(fmeme_data,"#Columns: fitness, popularity, lifetime.\n\n");
}
Everything is fine at this step: files are open and two lines are written on them.
Then I have a long simluation of a stochastic process, whose code is not interesting for the question's purposes: the files and their pointers are never used. At the end of the process I have:
for(i=0;i<data;i++){
fprintf(fmeme_data,"%f\t%d\t%f\n",meme[i].fitness,meme[i].popularity,meme[i].lifetime);
}
for(i=0;i<40;i++){
fprintf(ffitness_data,"%f\t%f\t%f\n",(1.0/40)*(i+0.5),popularity_histo[i],lifetime_histo[i]);
}
Then I DO fflush() and fclose() of both files.
If I make the code run on my laptop, both files are filled. If the code runs on a remote server, the file fitness_data.txt contains only the first print, i.e. the print starting with # but doesn't contain the data. I want you to note that:
The other file never gives me problems.
I'm used to this server. Something similar never happened.
Given all these information, the question is:
Why it is happening that a certain command, used always in the same way and in the same code, always works on a server while on a different server it works sometime but sometime it doesn't?
Admins: I don't think this question is a duplicate. All similar questions were solved by asjusting the code (here) or adding fflush() (here) and similar things. Here is not a problem in the code (in my modest opinion) because on my laptop it works. I bet it works on most.
We can't say for certain what's going on here, because we don't have your full program nor do we have access to the server where the problem happens. But, we can give you some debugging advice.
When a C program behaves differently on one computer than another, the very first thing you should suspect is memory corruption. The best available tool for finding memory corruption is valgrind. Fix the first invalid operation it reports and repeat until it reports no more invalid operations. There are excellent odds that the problem will have then gone away.
Turn up the warning levels as high as they can go and fix all of the complaints, even the ones that look silly.
You say you are calling fflush and fclose, but are you checking whether they failed? Check thoroughly, like this:
if (ferror(ffitness_data) || fflush(ffitness_data) || fclose(ffitness_data)) {
perror("write error on fitness_data.txt");
exit(1);
}
Does the problem go away if you change the optimization level you are compiling with? If so, you may have a bug that causes "undefined behavior". Unfortunately there are a lot of possible ways to do that and I can't easily explain how to look for them.
Use a tool like C-Reduce to cut your program down to a smaller program that still doesn't work correctly but is short enough to post here in its entirety.
Read and follow the instructions in the article "How to Debug Small Programs"..
I'm having trouble writing in a file, but the problem is that weird, I dont't even know for what I should exactly ask for.
At first: I use C, I am forced to keep it concurring to the 89/90-standard an to compile with gcc. My OS is Windows 7 Home Premium, 64Bit.
What I want to do, is to open three filestreams like this:
FILE *A=fopen("A.txt", "r");
FILE *B=fopen("B.txt", "w");
FILE *D=fopen("C.txt", "w");
The first one only to read, the two others to write. During the program, I write with
fprintf(B, "%c", letter);
fprintf(D, "%c", letter);
integers, interpreted as ASCII-charachters into the files. I did this twenty times before, it always worked. Now, the "D" file stays empty. If I change the order of the streams to:
FILE *A=fopen("A.txt", "r");
FILE *D=fopen("C.txt", "w");
FILE *B=fopen("B.txt", "w");
my file "B" stays empty! So always the last one opened does not work. But why?! I can't see any difference to my other programms, which are working, and this program also works, except in the case of this third filestream. I'm compiling with -Wall and -pedantic, the Compiler is not complaining, the Programm ist not crashing, everything works but the third stream!
Has anyone any idea, or even better, experience with a problem like this? I tried about one hour without getting any clue.
Edit: Thanks for alle the comments! I'm programming with C for about two months till now, so there are many things, I'm not really sure of.
#Mhd.Tahawi: Yes, now I did, but no difference.
#Kninnug: The files get opened succesfully.
#Bit Fiddling Code Monkey: Yes, as far as I know, there is a limit somewhere. But I worked with 6 filestreams at the same time a week ago and everything was fine.
#Pandrei: Yes, the Output in the other file was fine.
#Martin James: I'm not sure what you mean. If you mean fclose or something similar: Since so many of you asked me for this, I tried it, but there was no difference.
#hmjd: 'letter' is an integer that gets its value by fgetc(A);
#squeamish ossifrage: I'm printing sign by sign into the file an get '1' for each, seems to be ok.
Edit2: Now, that's nice, I'm facing some kind of Heisenbug. I was going to check the return values, as so many of you told me to.
So I initalized a new int retval=0; and wrote:
letter=fgtec(A);
while (letter!=EOF)
{
retval=fprintf(B, "%c", letter);
printf("%d", retval); /*Want to see the return values on stdout*/
if (retval<0) /*If writing fails, the program stops*/
{
printf("Error while writing in file");
return (-1);
}
letter=fgetc(A);
}
And this one works! New file gets filled, everything is fine. Except for the fact, that I have absolutely no idea, why the old one:
letter=fgtec(A);
while (letter!=EOF)
{
fprintf(B, "%c", letter);
letter=fgetc(A);
}
that worked tenthousand times before, didn't do anything at all.
Has anyone any further ideas? However, thanks so far for your ideas!
Unless you called fclose() your standard library will buffer the output data and you won't see it on disk until you either write enough, or flush it via fflush() or close the file via fclose() (or disable buffering via setbuf()/setvbuf()).
Obviously, disabling buffering or flushing after each I/O operation obviates the whole purpose of buffered I/O making performance suboptimal.
I think, I found the source of the problem, so I thought it might be helpful to share, that it seems to be compiler-related.
As written above, I use gcc as part of the MinGW-package.
I asked a friend of mine, who uses Pelles C, to compile the code himself and voila! For him, it worked fine!
So it seems like gcc has, under certain conditions, possibly problems with filestreams. But I can't really say, which conditions.
However, if anyone else has a problem like this, try it with another compiler!
I know this is a general question.
I'm going to program a compiler and I was wondering if it's better to take the tokens of the language while reading the file (i.e., first open the file, then extract tokens while reading, and finally close the file) or read the file first, close it and then work with the data in a variable. The pseudo-code for this would be something like:
file = open(filename);
textVariable = read(file);
close(file);
getTokens(textVariable);
The first option would be something like:
file = open(filename);
readWhileGeneratingTokens(file);
close(file);
I guess the first option looks better, since there isn't an additional cost in terms of main memory. However, I think there might be some benefits using the second option, for I minimize the time the file is going to be open.
I can't provide any hard data, but generally the amount of time a compiler spends tokenizing source code is rather small compared to the amount of time spent optimizing/generating target code. Because of this, wanting to minimize the amount of time the source file is open seems premature. Additionally, reading the entire source file into memory before tokenizing would prevent any sort of line-by-line execution (think interpreted language) or reading input from a non-file location (think of a stream like stdin). I think it is safe to say that the overhead in reading the entire source file into memory is not worth the computer's resources and will ultimately be detrimental to your project.
Compilers are carefully designed to be able to proceed on as little as one character at a time from the input. They don't read entire files prior to processing, or rather they have no need to do so: that would just add pointless latency. They don't even need to read entire lines before processing.
Is there a Windows equivalent to Linux's readahead syscall?
EDIT:
I would like a full function signature if possible, showing the equivalent offset/count parameters (or lower/upper).
Eg:
The Linux function signature is:
ssize_t readahead(int fd, off64_t *offset, size_t count);
and an example of it's use is
readahead(file, 100, 500);
Where "file" is a file descriptor previously set by a function like mmap. This call is reading 500 bytes at index 100.
EDIT 2:
Please read this if you are unsure what readahead does: http://linux.die.net/man/2/readahead
Yes. It is FileSystemControl FSCTL_FILE_PREFETCH.
It is used in Windows Vista and above for prefetching both when an application starts and at boot time.
It is also used by the SuperFetch technology that uses heuristics to load applications at approximately the times of day you generally use them.
FSCTL_FILE_PREFETCH itself is not documented on MSDN, but it is easy to figure out the parameter format by examining the DeviceIoControl calls made on app startup: Just start an application in the debugger that already has a .pf file in the c:\Windows\Prefetch directory and break on DeviceIoControl (or if you're using a kernel debugger, break when the NTFS driver receives its first FSCTL_FILE_PREFETCH). Examine the buffer passed in and compare it with the .pf file and the range actually used later. I did this once out of curiosity but didn't record the details.
In case you are unfamiliar with DeviceIoControl and IRP_MJ_FILESYSTEM_CONTROL, here are some links to look at:
FileSystemControl at the IRP level IRP_MJ_FILESYSTEM_CONTROL
DeviceIoControl, which is used to invoke FileSystemControl IRPs
Structure of IO Control Codes
As of Windows 8, there exists a more or less direct equivalent to madvise(MADV_WILLNEED), which is effectively the same thing (Windows has an unified VM/cache system).
Assuming that you have memory-mapped the file, you can thus use PrefetchVirtualMemory to prefetch it.
This is still slightly more complicated than you'd wish, but not nearly as harsh as DeviceIoControl. Also note that you can easily prefetch several independent, discontinuous ranges.
I am not sure if I understand correctly, in what you said 'Where "file" is a file descriptor previously set by a function like mmap. This call is reading 500 bytes at index 100.' That sounds suspiciously like seeking to the offset and read 500 bytes... but you want it to be pre-fetched ahead...
In C Code, it would look something like this:
fseek(fp, 100, SEEK_CUR);
fread(&data, 500, 1, fp);
But prefetching it, I guess, you would want to hook up some kind of events using waithandles, and when the event gets raised, the data gets stored somewhere in a buffer...
To be honest, I have not come across a such thing that does pre-fetching data...but Ray's answer surprised me, but then again it is only for Vista upwards, if you want to maintain compatibility...that's something to keep in mind... but the links below may be of help...
Ok, there was a blog discussing this, a library written in Delphi, the source code is here, browsing the code here, ok, it may not be what you want but it may help you point in the direction... Sorry if its not what you are looking for...
Hope this helps,
Best regards,
Tom.