Thursday 29 December 2016

c - Why gcc does not give a warning or error when invalid mode is used in fopen()?



I am practicing some practice questions in FILE IO in C. Below is one of the programs.



#include
#include

int main()
{
char fname[]="poem.txt";

FILE *fp;
char ch;
fp = fopen ( fname, "tr");
if (fp == NULL)
{
printf("Unable to open file...\n");
exit(1);
}
while((ch =fgetc(fp)) != EOF)
{

printf("%c",ch);
}
printf("\n");

return 0;
}


As you can see in the statement




  fp = fopen ( fname, "tr");


The mode "tr" is not a valid mode (as I understand). I was expecting gcc to give an error (or a warning) while compiling the above program. However, gcc does not give any error (or warning) while compiling it.



However, as expected, when i run the program it exits printing "Unable to open file..." which means fopen() returned NULL , because there was error while opening file.



-bash-4.1$ ./a.out
Unable to open file...
-bash-4.1$



(The file poem.txt exists so this is because of the invalid mode given to fopen(). I checked by changing the mode to "r" and it works fine displaying the content of "poem.txt")



-bash-4.1$ ./a.out
THis is a poem.

-bash-4.1$



I was expecting gcc to give an error (or warning) message for the invalid mode.



Why gcc does not give any error (or warning) for this ?


Answer



This is Undefined Behavior:



Per Annex J.2 "Undefined Behavior", it is UDB if:




—The string pointed to by the mode argument in a call to the fopen function does not exactly match one of the specified character sequences (7.19.5.3).





Although Annex J is informative, looking at §7.19.5.3:




/3 The argument mode points to a string. If the string is one of the following, the file is open in the indicated mode. Otherwise, the behavior is undefined.




Basically, the compiler can blow you off here - a standard library function name (and behavior) can be used outside of the inclusion of a standard header (for example, non-standard extensions, completely user-defined behavior, etc.). The Standard specifies what a conforming library implementation shall include and how it shall behave, but does not require you to use that standard library (or define behavior for a specific implementation explicitly specified as UDB territory: at this point, if your parameter types match it's a legal function call).




A really good lint utility might help you here.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...