Does scope impact, checking for errors while obtaining input from stdin or outputting to stdout? For example if I have a code body built in the following way:
void streamCheck(){
if (ferror(stdin)){
fprintf(stderr, "stdin err");
exit(1);
}
if (ferror(stdout)){
fprintf(stderr, "stdout err");
exit(2);
}
}
int main(){
int c = getchar();
streamCheck();
...
putchar(c)
streamCheck();
}
are the return values of ferror(stdin) / ferror(stdout) impacted by the fact that I am checking them in a function rather than in the main? If there is a better way to do this also let me know I am quite new to C.
As long as you call ferror on a particular stream before calling any other function on that stream you should be fine.
It doesn't matter that ferror is being called from a different function that getchar or putchar was called from.
There is no problem in your function. ferror() checks the error indicator of the FILE * that is passed as argument. In other words, the error indicator is a property of the file object and is directly obtainable from the FILE * pointer. Therefore, no matter where you call ferror() from, it will be able to determine if an error happened with the FILE * that is passed as argument (that is, of course, if the argument is valid).
are the return values of ferror(stdin) / ferror(stdout) impacted by
the fact that I am checking them in a function rather than in the
main?
The return value of ferror() is characteristic of the current state of the stream that you provide as an argument. At any given time, the stdin provided by stdio.h refers to the same stream, with the same state, in every function, including main(). Therefore, you will obtain the same result by calling the ferror() function indirectly, via an intermediary function, as you would by calling it directly.
NEVERTHELESS, the approach you present in your example is poor. For the most part, C standard library functions indicate whether an error has occurred via their return values. In particular, getchar() returns a special value, represented by the macro EOF, if either the end of the file is encountered or an error occurs. This is typical of the stdio functions. You should consistently test functions' return values to recognize when exceptional conditions have occurred. For stream functions, you should call ferror() and / or feof() only after detecting such a condition, and only if you want to distinguish between the end-of-file case and the I/O error case (and the "neither" case for some functions). See also "Why is 'while ( !feof (file) )' always wrong?"
Personally, I probably would not write a generic function such as your streamCheck() at all, as error handling is generally situation specific. But if I did write one, then I'd certainly have it test just one stream that I specify to it. Something like this, for example:
void streamCheck(FILE *stream, const char *message, int exit_code) {
if (ferror(stream)) {
fputs(message, stderr);
exit(exit_code);
}
}
int main(void) {
int c = getchar();
if (c == EOF) {
streamCheck(stdin, "stdin err\n", 1);
}
// ...
if (putchar(c) == EOF) {
streamCheck("stdout err\n", 2);
}
}
Related
I'm trying to understand when the stdio function clearerr() should be used.
For example, if I fread() or fwrite() on a valid FILE* and get a short count and ferror is true, what can I do?
From what I've read so far, fread() and fwrite() are robust and will block and/or retry (if there are locks and/or interrupts which could happen in lower level functions) so there never seems any point in using clearerr() because fread or fwrite errors will be so catastrophic there is no point in trying to recover.
Additionally, ferror() only tells me that there is an error, not what the error is.
#define SZ 1024
FILE* fp = fopen( "foo", "r" );
if ( fp ) {
char b[SZ];
int ch_count = fread( b, sizeof(char), SZ, fp );
if ( ch_count != SZ && ferror( fp ) ) {
// how would clearerr() be used. I don't know?
// ....
// should I drop through here to fclose? (when I've got an ferror)
}
fclose( fp );
}
There is at least one real world use case for clearerr: when you want to mimic tail -f on a file that is not opened in exclusive mode. That means that another (or many other) process(es) write at the end of a file, and one process repeatedly reads even after having reached the end of file in order to look whether new data has arrived. In that case, could would look like:
for (;;) {
if (NULL == fgets(line, sizeof(line), fd)) {
sleep(n);
clearerr(fd); // reset EOF condition
}
else {
fputs(line, fdout);
}
}
Functions that set the error status of a FILE (as reported by ferror) do not clear it even if later called successfully. Likewise if you encounter the end of file while reading, it will not be cleared automatically even if the file later has more data available.
Basically this means that if you are using ferror to check for an error state and you have some way of recovering from it, the ferror will keep indicating an error until you use clearerr.
In your example, if you just use the return value of fread as the condition for terminating the read (i.e., EOF and any type of error are considered final), there is no need to clearerr: just fall through to fclose (and perhaps use ferror to determine whether to print an error message).
On the other hand, if the FILE is in fact a stream on which read can later succeed, and you detect (or assume) that specific condition and retry, you should clearerr before retrying or you will keep seeing the old error condition on future attempts.
Likewise, as pointed out in comments, clearerr also clears the end of file state, so this also applies when using feof to check for the end of file. (Note, however, that you generally shouldn't use !feof(file) as the loop condition when reading.)
clearerr() clears the error and EOF flags from a stream.
Say FILE were like this:
typedef struct {
int fd;
char *buf;
int error;
int eof;
} FILE;
FILE *file;
This would set file->error and file->eof to 0.
Some reasons for doing this include file I/O, such as when a file gives EOF, but then another program (or another thread, etc.) appends to it. If you clear the error after doing this, you can have your program act as sort of a tail -f-substitute.
clearerr() clears both the error and end-of-file flags.
A pedantic use of clearerr():
// Return -1 on end-of-file
// Return -2 on rare file error
// Else return the unsigned char value
int my_get_quandry() {
// At this point, the file end-of-file flag may be set.
// At this point, the file file error flag may be set.
// They may both be set.
// Attempt to read another
int ch = fgetc();
if (ch != EOF) {
return ch;
}
// Now was the EOF due to a end-of file or error?
// feof() is true if end-of-file just occurred OR if end-of-file was set earlier
// ferror() is true if error just occurred OR if error was set earlier
// If only one feof() or ferror() is true, we know why EOF just occurred,
// Yet if both set, we do not know.
...?
}
Use clearerr()
// Return -1 on end-of-file
// Return -2 on rare file error
// Else return the unsigned char value
int my_get_crystal() {
clearerr(stdin);
// Attempt to read another
int ch = fgetc();
if (ch != EOF) {
return ch;
}
// Now EOF due to at most one reason
if (feof(stdin)) return -1;
if (ferror(stdin)) return -2;
// if code reaches this point, it is due to the odd-ball platform of `char` having the
// same range as `int`. But let us leave that platform for another day.
return ch;
}
From man page of fwrite in linux,
DESCRIPTION
The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.
The function fwrite() writes nmemb elements of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by ptr.
For nonlocking counterparts, see unlocked_stdio(3).
RETURN VALUE
On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1. If an error occurs, or the end of the file is reached,
the return value is a short item count (or zero).
fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.
Now my question is:
Suppose fwrite() system call failure occurred due to No space on the drive. How can we get the errno for it. As fwrite is not setting the errno in case of failure.
Just in case errno is:
The header file defines the integer variable errno, which
is set by system calls and some library functions in the event of an
error to indicate what went wrong.
Talking in terms of Programming language: C
fwrite() is not a direct system call, and in general all I/O done via a FILE * pointer is buffered. There is no guarantee that a call to fwrite() will actually perform a write at that time. Errors can be returned immediately, or by later calls to functions using FILE *. However, fclose() will write out any remaining buffered data, and will return an error if that write did not succeed.
In summary, you need to check for errors during every call to fwrite(), fread() and fclose(). If you want to avoid doing error checking everywhere, you can call ferror() at any time to check the error status of a FILE *.
The variable errno is set when errors occur, because the C library internally calls read() and write(), and those set errno in case of errors.
fwrite() cannot fail due to EOF, but fread() can.
For fwrite(), you discover an error if it did not write the same amount of items you told it to, so you check it like this:
size_t written = fwrite(buf, element_size, num_elements, file);
if (written != num_elements) {
//error , here errno do get set and you can inspect it/print it etc.
}
Now, a FILE* have an internal buffer, so a fwrite() call might not actually write the data to the operating system or file unless that internal buffer gets full.
This means you also either have to fflush() the FILE* and also check for errors after each fwrite() call like so:
if (fflush(file) == EOF) {
//error , here errno do get set and you can inspect it/print it etc.
}
Or you have to accept that a potential write failure can be given to you on any future fwrite() calls you perform if e.g. those calls happens to flush() the FILE* automatically.
And you'd also have to check for errors when calling fclose():
if (fclose(file) == EOF) {
//error , here errno do get set and you can inspect it/print it etc.
}
For fread() you can inspect errno if it failed. After you have handled any data an fread() call have read, you can do
if (ferror(file)) {
//error , here errno do get set and you can inspect it/print it etc.
}
As fwrite is not setting the errno in case of failure: not exactly. The only possible error for fwrite is an error that would occur during the call of the underlying write system call. In that case the errno variable will be set but the write call and as such will be available, and you will be able to directly use the strerror or perror functions to get a textual description of the error.
BTW, fwrite is not a system call but a standard library function: is does not directly call a kernel function.
I have to individually read characters and substrings from a stream in C while parsing them. I wish also to check for input error. The obvious way to do this is something like:
c = fgetc(f);
if(ferror(f)) {
puts(strerror(errno));
exit(1);
}
/* do something with c */
c = fgetc(f);
if(ferror(f)) {
puts(strerror(errno));
exit(1);
}
/* do something with c */
Etc. However, it would be much more practical and fast (in the non-exceptional case when there's no error) if I could do all the input operations and check for the error indicator later:
c = fgetc(f);
/* do something with c */
c = fgetc(f);
/* do something with c */
if(ferror(f)) {
puts(strerror(errno));
exit(1);
}
This would be possible if input operations like fgetc(), scanf() etc were simple passthrough no-ops when the error indicator of f is set. Say, an error occours in the first fgetc() and therefore the second fgetc() is a no-op that fails but change neither the error indicator of f nor errno.
A similiar question may be asked about output functions.
My question is: is this the behaviour of stdio functions? May I check ferror(f) after all operations and get errno then if I am sure that all those "do something with c" do not change errno?
Thanks!
No, those are not the defined semantics of errno.
Quoting this manual page:
Its value is significant only when the return value of the call indicated an error (i.e., -1 from most system calls; -1 or NULL from most library functions); a function that succeeds is allowed to change errno.
This implies that if you were to do two I/O operations where the first fails, and the second is a "no-op" (like read zero bytes) it could succeed and opt to clear errno, thus dropping the error set by the first call.
Answering my own question, it seems that the reliable way to implement what I was looking for is to write a wrapper function myfgetc(), as Michael Walz suggested, together with a global variable myerrno:
__thread int myerrno = 0;
int myfgetc(FILE *f) {
int c;
if(myerrno)
return EOF;
if((c = fgetc(f)) == EOF)
myerrno = errno;
return c;
}
The storage class __thread is added to myerrno so that every thread has its own myerrno. It can be ommited if the program is single threaded.
...is this (an error occurs in the first fgetc() and therefore the second fgetc() is a no-op that fails) the behaviour of stdio functions?
No - not a no-op.
FILE has: "an error indicator that records whether a read/write error has occurred," (C11dr § § 7.21.1 2), not that an error just occurred. It is a flag that accumulates the history of read errors.
For fgetc() and friends,
If a read error occurs, the error indicator for the stream is set and the fgetc function returns EOF. C11dr § 7.21.7.1 3.
This return of EOF due to input error differs from EOF due to end-of-file. The latter has an or "If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF". EOF due to input error does not have an or.
I interpret this to imply that the error indicator of the stream can be true and fgetc() does not return EOF as the byte just read was not in error.
How a stream error indicator affects following input code? may be useful.
May I check ferror(f) after all operations and get errno then if I am sure that all those "do something with c" do not change errno?
errno not that useful here. C does not specify any I/O functions as certainly setting errno - that is an extension of some compilers. C expressly prohibits standard functions from clearing errno.
Yes, code can check ferror(f) to see if an error had occurred sometime in the past. Examination of errno is not needed.
To clear both error indicator and end-of-file, research clearer().
I'm curious about the function signature for yyrestart - namely in the lexer file I see that the signature is:
void yyrestart (FILE * input_file )
In my code I use yyrestart to flush the buffer, but I haven't been passing it any argument, it's just been empty:
yyrestart();
Which is currently working on every system we test on except for the latest version of OS X. Stepping through with GDB, it's clear on my rhel machine that just calling with no argument sets the file pointer to NULL:
yyrestart (input_file=0x0) at reglexer.c:1489
Whereas on El Capitan it comes through as garbage, which is causing the mem error later in generated code:
yyrestart (input_file=0x100001d0d) at reglexer.c:1489
I can't for the life of me figure out where yyrestart() is defined. Is there some macro in yacc/flex that defines the behavior for calling yyrestart with no arguments? If not, how is this even compiling?
*********** EDIT to Clarify the Compiling Question ************
As a small snippet to see what I'm talking about - this is what I have in a my .y file, which is executing the parser (this is a SLIGHT modification of what's this example):
int main() {
FILE *myfile = fopen("infile.txt", "r");
if (!myfile) {
fprintf(stderr, "can't open infile.txt\n");
return 1;
}
calcYYin = myfile;
do {
calcYYparse();
} while (!feof(calcYYin));
calcYYrestart();
return 0;
}
I can build that repository with whatever I want passed in as arguments to calcYYrestart() on that line. Substituting
calcYYrestart('a', 1, 5, 'a string');
still lets me compile the entire program using make (but a get a segv with bad input). But looking through the generated parcalc.c file, I don't see anything that would allow me to call calcYYrestart with anything except for a file pointer. I only see this as the prototype:
void calcYYrestart (FILE * input_file );
Where's the magic happening with the compiler that lets me put whatever I want as arguments to that generated function?
You are expecting C to gently lead you through the maze, holding your hand, chiding you when you err and applauding your successes.
These may not be unreasonable expectations for a language, but C is not that language. C does what you tell it to do, nothing more, and when your instructions fall short of clarity, it simply lets you fall.
Although, in its defense, you can ask it to be a bit more verbose. If you specify -Wall on the command line (at least with gcc and clang), the compiler will provide you with some warnings. [See note 1.]
In this case, it probably would have warned you that calcYYrestart was not declared, which would make it your responsibility to get the arguments right. The function is declared and defined in the lexer, but here you are using it in the parser, which is a separate compilation unit. You really should declare it in the parser prologue, but nothing will enforce the correctness of that declaration. (C++ would fail to link in that case, but C does not record argument types in the formal function name.)
It's worth noting that there are many problems with the sample code you are basing your work on. I'd suggest looking for a better bison/flex tutorial, or at least reading through the sections in the flex manual about how input is handled.
Here, I've added some annotations to the original example, which shows the calc.y bison input file:
/* This is unnecessary, since `calcYYparse` is defined in this file.
extern int calcYYparse();
*/
extern FILE *calcYYin;
/* Command line arguments are always good */
int main(int argc, char** argv) {
/* If there is an argument, use it. Otherwise, stick with stdin */
/* There is no need for a local variable. We can just use yyin */
if (argc > 1) {
calcYYin = fopen(argv[1], "r");
if (!calcYYin) {
fprintf(stderr, "can't open infile.txt\n");
return 1;
}
}
/* calcYYin = myfile; */
/* This loop is unnecessary, since yyparse parses input until it
* reaches EOF, unless it hits an error. And if it hits an error, it
* will call calcYYerror (below), which in turn calls exit(1), so it
* never returns.
*/
/* do { */
calcYYparse();
/* } while (!feof(calcYYin)); */
return 0;
}
void calcYYerror(const char* s) {
fprintf(stderr, "Error! %s\n", s);
/* Valid arguments to `exit` are 0 and small positive integers. */
exit(EXIT_FAILURE);
}
Of course, you probably don't want to just blow up the world if you hit a syntax error. The intention was probably to discard the rest of the line and then continue the parse. In that case, for obvious reasons, callYYerror should not call exit().
By default, after yyerror is called, yyparse returns immediately (after cleaning up its local storage) with an error indication. If you want it to instead continue, then you need to use an error production, which would be the best solution.
You could also simply call yyparse again, as in the example. However, that leaves an unknown amount of the input file in the flex buffer. There is no reason to believe that the buffer contains exactly the rest of the line in error. Since flex scanners typically read there input in large chunks (except for interactive input), resetting the input file with yyrestart will discard a random amount of input, leaving the input file pointer at a random position in the file, which probably does not correspond with the beginning of a new line.
Even if that were not the case, as with unbuffered (interactive) input, it is entirely possible that the error was detected at the end of a line, in which case the new line will already have been consumed. So discarding to the end of the current line will result in discarding the line following the error.
Finally, the use of feof(input) to terminate input loops is a well-known antipattern, and should be avoided in favour of terminating when an EOF is encountered while reading input. In the case of flex-generated scanners, when EOF is detected, the current input is discarded, and then (if yywrap doesn't succeed in creating a new input), the END indication is returned to the parser. By then, yyin is no longer valid (because it was discarded), and calling feof on it is undefined behaviour.
Notes
You get even more warnings by also specifying -Wextra. And you can make the compiler a little stricter by telling it to use the latest standard, -std=c11, instead of the 1989 version augmented with various gcc extensions, mostly now outdated.)
For my assignment I have to create a program similar to the -wc unix command which counts words, lines, etc.
I have to read in flags and read in a text file.
I've set up all the flags and now I'm trying to read in a text file. I don't think I'm doing this right.
void readInFile(char** argv, int arg)
{
FILE *myFile;
char c;
myFile = fopen(argv[arg], "r");
if(!myfile)
{
printf("%s not found!", argv[arg]);
exit(EXIT_FAILURE);
}
}
in my main I call the function readInFile() and pass 2 arguments. Argv and the element where the file should be. So assume this to be correct.
I need help with actually opening up the file. I feel like my fopen() is wrong. I'm new to reading/writing files in C. Thanks alot!
I'm going to give you some general advice here.
Usually functions should do a single job. In this case, you are writing a function to read in a single file. So, don't pass a pointer to all the command-line arguments; pass in a single read-only pointer to the name of the file to open. Then in main() select the correct argument and pass that as the argument.
void readInFile(char const *filename)
Now, if this function will be reading in the file and doing nothing else, it needs to return the data somehow. But if this function will be doing the equivalent of wc, maybe it will read the file and print stuff, not return any data to the main() function. Then maybe the name should be improved:
void wordcount(char const *filename)
The actual call to fopen() looks fine to me.
You check for error, and then call exit() immediately. That's one way to do it. Another way to do it is to return an error code from your function, and have the caller (the main() function) check for failure, and handle the error there.
int wordcount(char const *filename)
{
// ... do stuff
if (failed)
return 1; // return nonzero error code on failure
// ... do more stuff
return 0; // success code
}
int main(int argc, char const **argv)
{
char const *filename;
int result;
filename = argv[1];
result = wordcount(filename);
if (result)
{
fprintf(stderr, "unable to open file '%s'\n", filename, result);
exit(result);
}
return 0;
}
For a program this simple, it doesn't matter much. But once you start building larger systems in software, you will be happier if your functions work well together, and part of that is making functions that return error codes rather than terminating your whole program on any error.
Why am I using 0 for the success code, and non-zero for failure? It's a common way to do it. It's easy to test for non-zero, like if (result) and there are many non-zero codes but only one zero, so you can return many different kinds of errors, but there is only one value needed for "success".
Note that instead of calling exit() from main(), you can just use the return statement. When you return 0 from main(), that signals success, and a non-zero value indicates an error. So you could just use return result; from main() if you like.
In my dummy code, I'm just returning 1 as the error code. But actually, when you call fopen() it returns an error code to you, in a global variable called errno. Probably a better option is to make your function return the actual error code as specified in errno. You could even modify the print statement in the main() function print the errno code, or use the strerror() function to turn that error code into a human-readable message.
Your call to fopen is correct, assuming that argv[arg] is a valid string which refers to a file that exists on the filesystem.
There is a small typo in the program snippet. if(!myfile) should prpbably be if(!myFile). With this change, I presume the code should work. Can you please elaborate the error faced by you?
P.S: I tried your program and it seems to work!