By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,081 Members | 2,118 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,081 IT Pros & Developers. It's quick & easy.

Qry : Behaviour of fgets -- ?

P: n/a

Machine 1 :
bash-3.00$ uname -a
SunOS <hostname5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R

bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)
Machine 2:
bash-2.05b$ uname -a
Linux <hostname2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux

bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)

bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".

Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

please ignore if it is known and would be great if you can point out
in the implementation detail.
--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007

Sep 6 '07 #1
Share this Question
Share on Google+
285 Replies


P: n/a
Sheth Raxit wrote:
[...]
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.
[...]

I see no direct reference in the standard to what should happen. The
closest thing I see (and it's not very close) is 7.19.3p4:

The value of a pointer to a FILE object is indeterminate after
the associated file is closed (including the standard text
streams).

However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.

My guess is that this is UB.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Sep 6 '07 #2

P: n/a
Sheth Raxit wrote:
Machine 1 :
bash-3.00$ uname -a
SunOS <hostname5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R

bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)
Machine 2:
bash-2.05b$ uname -a
Linux <hostname2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux

bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)

bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".

Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

please ignore if it is known and would be great if you can point out
in the implementation detail.
--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007
The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Description
The fgets function reads at most one less than the
number of characters specified by n from the stream
pointed to by stream into the array pointed to by s.
No additional characters are read after a new-line
character (which is retained) or after end-of-file.
A null character is written immediately after the
last character read into the array.

Returns
The fgets function returns s if successful. If
end-of-file is encountered and no characters have been
read into the array, the contents of the array remain
unchanged and a null pointer is returned. If a read
error occurs during the operation, the array contents
are indeterminate and a null pointer is returned.
----------------------------------------------------
Nothing is said about

File stream is NULL
int n is <= 0
char *s is NULL
Sep 6 '07 #3

P: n/a
Sheth Raxit <ra************@gmail.comwrites:
Machine 1 :
bash-3.00$ uname -a
[SNIP]
Machine 2:
bash-2.05b$ uname -a
[SNIP]

The details of your system aren't relevant to your problem. (If they
were, comp.lang.c probably wouldn't be the place to ask about it.)
I've redirected followups to comp.lang.c (which probably won't do any
good.)
bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>
[SNIP]

The formatting of your code makes it difficult to read. Here's a
cleaned-up version:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100], sendrepfile[100];
FILE *spfp = NULL;
memset(sendrepfile, 0, 100);
strcpy(sendrepfile, "/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s", sendrepfile);
fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent, 40, spfp) != NULL)
{
printf("The value of spcontent is [%s]", spcontent);
fflush(stdout);
}
return 0;
}

You check whether the fopen() call succeeded or not. If it fails, you
print an error message.
You then attempt to read from the file *even if the fopen() call
failed*.

fgets() is not required to check whether its third argument is valid;
it can simply assume that it is. The standard's description (I'll use
'*'s to denote boldface) is:

The *fgets* function reads at most one less than the number of
characters specified by *n* from the stream pointed to by *stream*
into the array pointed to by *s*.

If there is no "stream pointed to by *stream*", then the behavior is
undefined. A segmentation fault is not surprising.

If you fail to open the file, don't try to read from it.

A few other remarks:

You don't use anything from <stdlib.h>.

'int main(void)' is preferred to 'int main()', though both are valid.

Avoid "magic numbers" like 100. Define a symbolic constant so that
you only have to change it in one place. You use a literal 100 in one
memset call, sizeof() in the other.

Both memsets are unnecessary. spcontent and sendrepfile are used to
hold strings; it doesn't matter what's in the array past the
terminating '\0'.

The cast to FILE* is unnecessary (as are most casts); you can just
compare the result of fopen() to NULL.

You print your error message to stdout. Error messages should normally
be written to stderr.

Your outputs should be terminated with '\n' unless you have a specific
reason not to. In particular, you should definitely have a '\n' at
the very end of your program's output.

The fflush(stdout) calls should be on lines by themselves; I almost
didn't notice them before I reformatted your code.

You declare spcontent as an array of 100 characters, but you only
attempt read at most 40 characters into it. Using symbolic constants
(say, '#define MAX_LINE_LENGTH 40') would make it easier to keep these
consistent.

You have a double semicolon on the second fflush() call. It happens
to be harmless, but there's no reason for it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 6 '07 #4

P: n/a
Sheth Raxit wrote:

<snip>
<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
<snip>
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?
Then the behaviour is undefined, meaning that anything can happen
(including a crash as you experienced).
fgets() is defined to read characters from the stream pointed at by the
argument stream, but a null-pointer does not refer to any stream.
>
As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.
Your understanding is incorrect. There is no such requirement for
fgets().
The fgets() implementation may simply assume that all pointers passed
into it are valid. Some may have implemented a precondition check on
this assumption, but that is certainly not universal. And a failed
check may just as easily be regarded as a fatal error.
>
please ignore if it is known and would be great if you can point out
in the implementation detail.
--Gaurav Gupta & Raxit Sheth
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
Sep 6 '07 #5

P: n/a
On Sep 7, 12:54 am, Keith Thompson <ks...@mib.orgwrote:
Sheth Raxit <raxitsheth2...@gmail.comwrites:
Machine 1 :
bash-3.00$ uname -a
[SNIP]
Machine 2:
bash-2.05b$ uname -a

[SNIP]

The details of your system aren't relevant to your problem. (If they
were, comp.lang.c probably wouldn't be the place to ask about it.)
I've redirected followups to comp.lang.c (which probably won't do any
good.)
agree
>

bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */
int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));
while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>

[SNIP]

The formatting of your code makes it difficult to read. Here's a
cleaned-up version:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100], sendrepfile[100];
FILE *spfp = NULL;
memset(sendrepfile, 0, 100);
strcpy(sendrepfile, "/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s", sendrepfile);
fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent, 40, spfp) != NULL)
{
printf("The value of spcontent is [%s]", spcontent);
fflush(stdout);
}
return 0;

}

You check whether the fopen() call succeeded or not. If it fails, you
print an error message.

You then attempt to read from the file *even if the fopen() call
failed*.
Yes, we know that is incorrect but to re-product the behaviour. i.e.
you can say fgets Test code.
>
fgets() is not required to check whether its third argument is valid;
it can simply assume that it is. The standard's description (I'll use
'*'s to denote boldface) is:

The *fgets* function reads at most one less than the number of
characters specified by *n* from the stream pointed to by *stream*
into the array pointed to by *s*.

If there is no "stream pointed to by *stream*", then the behavior is
undefined. A segmentation fault is not surprising.
Can not it more useful, if standard suggest to returns the NULL, if
stream is NULL., than of Undefined behaviour. ?

By this, every implementation <conforming to standardwill check
if (fgets==NULL) then Instead of Undefined behaviour, it will return
NULL. <or proper error handling.>

it is like introducing new Test Case for fgets <and i think related
simillar functions.>
All your remarks/suggestion are very much valid, assume our code as
small test program which fails on some platform.

If you fail to open the file, don't try to read from it.
yes,but we are checking currently the behaviour of fgets.
A few other remarks:

You don't use anything from <stdlib.h>.
we have used exit if fopen returns NULL, but intentionally we remove
exit,to check the behaviour of fgets.
>
[deleted]
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -

- Show quoted text -

-Raxit & Gaurav

Sep 7 '07 #6

P: n/a
On Sep 6, 11:27 pm, jacob navia <ja...@jacob.remcomp.frwrote:
Sheth Raxit wrote:
Machine 1 :
bash-3.00$ uname -a
SunOS <hostname5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R
bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)
Machine 2:
bash-2.05b$ uname -a
Linux <hostname2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux
bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)
bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */
int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));
while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?
As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.
please ignore if it is known and would be great if you can point out
in the implementation detail.
--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007<----BarCampMumbaiOct2007

The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Description
The fgets function reads at most one less than the
number of characters specified by n from the stream
pointed to by stream into the array pointed to by s.
No additional characters are read after a new-line
character (which is retained) or after end-of-file.
A null character is written immediately after the
last character read into the array.

Returns
The fgets function returns s if successful. If
end-of-file is encountered and no characters have been
read into the array, the contents of the array remain
unchanged and a null pointer is returned. If a read
error occurs during the operation, the array contents
are indeterminate and a null pointer is returned.
----------------------------------------------------
Nothing is said about

File stream is NULL
int n is <= 0
char *s is NULL- Hide quoted text -
don't you think instead of "not saying" or "saying undefined
behaviour" any additional checks are put itself in std ?
>
- Show quoted text -

Sep 7 '07 #7

P: n/a
Sheth Raxit <ra************@gmail.comwrites:
On Sep 7, 12:54 am, Keith Thompson <ks...@mib.orgwrote:
[...]
>fgets() is not required to check whether its third argument is valid;
it can simply assume that it is. The standard's description (I'll use
'*'s to denote boldface) is:

The *fgets* function reads at most one less than the number of
characters specified by *n* from the stream pointed to by *stream*
into the array pointed to by *s*.

If there is no "stream pointed to by *stream*", then the behavior is
undefined. A segmentation fault is not surprising.

Can not it more useful, if standard suggest to returns the NULL, if
stream is NULL., than of Undefined behaviour. ?

By this, every implementation <conforming to standardwill check
if (fgets==NULL) then Instead of Undefined behaviour, it will return
NULL. <or proper error handling.>

it is like introducing new Test Case for fgets <and i think related
simillar functions.>
Yes, such a change could be made, but passing a null pointer to fgets
(or to most standard library functions) is only one of a nearly
infinite number of possible errors. fgets() could detect a null
pointer, but it couldn't reasonably detect all possible invalid
arguments. The burden is on the programmer to avoid passing invalid
arguments; fgets() just has to work properly if it the arguments are
valid.

And if the standard committee decided to require fgets() to behave
reasonably with a null pointer argument, it would be literally decades
before all implementations would conform.

[...]
>If you fail to open the file, don't try to read from it.
yes,but we are checking currently the behaviour of fgets.
Strictly speaking, you're checking the behavior of one implementation
of fgets.

[...]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 7 '07 #8

P: n/a
Sheth Raxit <ra************@gmail.comwrites:
[...]
don't you think instead of "not saying" or "saying undefined
behaviour" any additional checks are put itself in std ?
No, the behavior is undefined.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 7 '07 #9

P: n/a
Kenneth Brody <ke******@spamcop.netwrites:
>However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.
>My guess is that this is UB.
Since he's not passing a pointer to a STREAM I'd also say it's UB.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Sep 7 '07 #10

P: n/a
On 6 Sep, 18:38, Sheth Raxit <raxitsheth2...@gmail.comwrote:

<snip>
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
why the strcpy()? why not:-

if ((spfp = fopen ("/tmp/filenotexists", "r")) == NULL)

or initialise sendfilerep when you define it.

char sendrepfile [] = "/tmp/filenotexists";

<snip>
--
Nick Keighley

in comp.lang.c, the very people most capable of making the inference
are those least likely to make it. This newsgroup considers pedantry
to be an art form.
Richard Heathfield

Sep 7 '07 #11

P: n/a
On Sep 7, 1:08 pm, Casper H.S. Dik <Casper....@Sun.COMwrote:
Kenneth Brody <kenbr...@spamcop.netwrites:
However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.
My guess is that this is UB.

Since he's not passing a pointer to a STREAM I'd also say it's UB.
Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.

I am asking to first make change in standard to have "few Undefined
Behaviour" when platform can handle. Technically platform may return
NULL, and handle this test case. Let me know if i am buffling
something/everything. ?

-Raxit
>
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

Sep 7 '07 #12

P: n/a
On Sep 7, 1:36 pm, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
On 6 Sep, 18:38, Sheth Raxit <raxitsheth2...@gmail.comwrote:

<snip>
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */
int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");

why the strcpy()? why not:-
This is not a point of Query ? why are we having trouble with strcpy/
individual coding style ?
Is it not confirming to std. ?
ignored
Sep 7 '07 #13

P: n/a
On Sep 7, 12:32 pm, Keith Thompson <ks...@mib.orgwrote:
Sheth Raxit <raxitsheth2...@gmail.comwrites:
On Sep 7, 12:54 am, Keith Thompson <ks...@mib.orgwrote:
[...]
fgets() is not required to check whether its third argument is valid;
it can simply assume that it is. The standard's description (I'll use
'*'s to denote boldface) is:
The *fgets* function reads at most one less than the number of
characters specified by *n* from the stream pointed to by *stream*
into the array pointed to by *s*.
If there is no "stream pointed to by *stream*", then the behavior is
undefined. A segmentation fault is not surprising.
Can not it more useful, if standard suggest to returns the NULL, if
stream is NULL., than of Undefined behaviour. ?
By this, every implementation <conforming to standardwill check
if (fgets==NULL) then Instead of Undefined behaviour, it will return
NULL. <or proper error handling.>
it is like introducing new Test Case for fgets <and i think related
simillar functions.>

Yes, such a change could be made, but passing a null pointer to fgets
(or to most standard library functions) is only one of a nearly
infinite number of possible errors. fgets() could detect a null
pointer, but it couldn't reasonably detect all possible invalid
arguments. The burden is on the programmer to avoid passing invalid
Interesting, !
yes there are many possible way except null pointer, do you think
which is the most frequently occuring ?

Yes after all it is the programmer,
arguments; fgets() just has to work properly if it the arguments are
valid.

And if the standard committee decided to require fgets() to behave
reasonably with a null pointer argument, it would be literally decades
before all implementations would conform.
you may correct, i am really not very much in related to std stuff,
this is what i think should/can be done.
>
[...]
If you fail to open the file, don't try to read from it.
yes,but we are checking currently the behaviour of fgets.

Strictly speaking, you're checking the behavior of one implementation
of fgets.
yes, i have checked and Behaviour is Undefined for particular
implementation, which might be corrected if std says or implementar
implements.

Let me find some time, if i can try to have patch for some most widely
used platform. <or better if you are reading this, and you are
platform implementor, you may correct this stuff.>
>
[...]

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -

- Show quoted text -
Thanks,
Raxit
http://www.barcamp.org/BarCampMumbaiOct2007<---BarCampMumbaiOct2007

Sep 7 '07 #14

P: n/a
Sheth Raxit <ra************@gmail.comwrites:
>On Sep 7, 1:08 pm, Casper H.S. Dik <Casper....@Sun.COMwrote:
>Kenneth Brody <kenbr...@spamcop.netwrites:
>However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.
My guess is that this is UB.

Since he's not passing a pointer to a STREAM I'd also say it's UB.
>Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.
No. The standard should not make it easier for buggy programs to
blunder on.

The implementation is doing you a favour by dumping core for this
particular bit of undefined behaviour. You have a bug in your program
(you invoke undefined behaviour, always a bug). If you had continued
onwards, your codee would not have made a distinction between
"file not found" and "file is empty". Perhaps not relevant for you,
but in other cases this might hide a serious bug in the program.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Sep 7 '07 #15

P: n/a
jacob navia <ja***@jacob.remcomp.frwrites:
>Nothing is said about error handling. It is just
>"UNDEFINED".
Yes. And when a programmer invokes "undefined" behaviour
*ANYTHING* can happen.

It's not quite the same as "no errors should happen"; it's
"thou shalt not invoke undefined behaviour".

The reason why this behaviour is undefined and why implementors
are free to ignore this is fairly straight forward:

- it's prohibitively expensive to test for any possible
form of undefined behaviour
Why stop at (FILE *)NULL; why not test for
(FILE *)0x1 or any non-mapped or non-aligned pointer or
pointer not returned by f*open?

- undefined behaviour is only invoked by programs with bugs
in it so why should other programs pay for this?

Dumping core is a good thing; you have a bug, it was caught. Now go
and fix your code.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Sep 7 '07 #16

P: n/a
Casper H.S. Dik wrote:
Sheth Raxit <ra************@gmail.comwrites:
>On Sep 7, 1:08 pm, Casper H.S. Dik <Casper....@Sun.COMwrote:
>>Kenneth Brody <kenbr...@spamcop.netwrites:
However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.
My guess is that this is UB.
Since he's not passing a pointer to a STREAM I'd also say it's UB.
>Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.

No. The standard should not make it easier for buggy programs to
blunder on.
[snip]
>
Casper
Even better would be to specify what to do when one
of the parameters is wrong...

Sep 7 '07 #17

P: n/a
Casper H.S. Dik said:

<snip>
The standard should not make it easier for buggy programs to
blunder on.
Agreed.
The implementation is doing you a favour by dumping core for this
particular bit of undefined behaviour.
Agreed.
You have a bug in your program
Agreed.
(you invoke undefined behaviour, always a bug).
Here, however, I must beg to differ. There are times when one must
invoke undefined behaviour if one is to get something done.

It is not a bug to point directly at video memory, for example. Yes, to
do this will necessarily make your code non-portable. Yes, you're
leaving behind all the guarantees that the Standard offers. But no, it
is not a bug, if one is deliberately setting out to write that code to
achieve one's goal because the Standard doesn't offer any satisfactory
way to achieve it.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 7 '07 #18

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
>Here, however, I must beg to differ. There are times when one must
invoke undefined behaviour if one is to get something done.
Such as? You are nopt confusing implementation defined behaviour
with undefined behaviour?
>It is not a bug to point directly at video memory, for example. Yes, to
do this will necessarily make your code non-portable. Yes, you're
leaving behind all the guarantees that the Standard offers. But no, it
is not a bug, if one is deliberately setting out to write that code to
achieve one's goal because the Standard doesn't offer any satisfactory
way to achieve it.
Ah, yes, but I would say that such things are covered by
"extensions to the standard" rather than down-right undefined
behaviour.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Sep 7 '07 #19

P: n/a
Casper H.S. Dik wrote:
jacob navia <ja***@jacob.remcomp.frwrites:
>Nothing is said about error handling. It is just
>"UNDEFINED".

Yes. And when a programmer invokes "undefined" behaviour
*ANYTHING* can happen.

It's not quite the same as "no errors should happen"; it's
"thou shalt not invoke undefined behaviour".

The reason why this behaviour is undefined and why implementors
are free to ignore this is fairly straight forward:

- it's prohibitively expensive to test for any possible
form of undefined behaviour
Why stop at (FILE *)NULL; why not test for
(FILE *)0x1 or any non-mapped or non-aligned pointer or
pointer not returned by f*open?

- undefined behaviour is only invoked by programs with bugs
in it so why should other programs pay for this?

Dumping core is a good thing; you have a bug, it was caught. Now go
and fix your code.

Casper
Why error analysis is necessary?

Error analysis means trying to have a defined an in all cases
identical reaction to program errors.

This means that for each function we write, we try to
return a specified error report value if things go wrong.

In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.

This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.
Sep 7 '07 #20

P: n/a
jacob navia wrote:
Casper H.S. Dik wrote:
>jacob navia <ja***@jacob.remcomp.frwrites:
>>Nothing is said about error handling. It is just
>>"UNDEFINED".

Yes. And when a programmer invokes "undefined" behaviour
*ANYTHING* can happen.

It's not quite the same as "no errors should happen"; it's
"thou shalt not invoke undefined behaviour".

The reason why this behaviour is undefined and why implementors
are free to ignore this is fairly straight forward:

- it's prohibitively expensive to test for any possible
form of undefined behaviour
Why stop at (FILE *)NULL; why not test for
(FILE *)0x1 or any non-mapped or non-aligned pointer or
pointer not returned by f*open?

- undefined behaviour is only invoked by programs with bugs
in it so why should other programs pay for this?

Dumping core is a good thing; you have a bug, it was caught. Now go
and fix your code.

Casper

Why error analysis is necessary?

Error analysis means trying to have a defined an in all cases
identical reaction to program errors.

This means that for each function we write, we try to
return a specified error report value if things go wrong.

In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.
o Testing for a bad value of n (maximum possible line length)

o Testing that the non-null buffer points to a legal C object
containing at least the `n` characters required

o Testing that the non-null stream points to a legal C object
This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.
If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.

--
Chris "serious about frivolity" Dollin

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Sep 7 '07 #21

P: n/a
Chris Dollin wrote:
jacob navia wrote:
>Why error analysis is necessary?

Error analysis means trying to have a defined an in all cases
identical reaction to program errors.

This means that for each function we write, we try to
return a specified error report value if things go wrong.

In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.

o Testing for a bad value of n (maximum possible line length)
That would be another integer comparison, but I do not
see immediately where you get this value: "maximum
possible line length"...
o Testing that the non-null buffer points to a legal C object
containing at least the `n` characters required

o Testing that the non-null stream points to a legal C object
In general, this is impossible and in the best case it would
repeat in software the tests done by the hardware.

Yes, maybe in some systems this is possible and very cheap.
But you are just making a caricature of what I said, a
well known way of discussion without being serious.

>This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.

If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.
No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.

Engineering is a long list of compromises. You have to test what can be
tested and not more but not less.
Sep 7 '07 #22

P: n/a
On Fri, 07 Sep 2007 12:40:38 +0200, jacob navia wrote:

[snip]
[about checking whether fgets() is called with either s or stream
being NULL or n being nonpositive]
>>This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.

If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.
No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.

Engineering is a long list of compromises. You have to test what can be
tested and not more but not less.
Avoiding to call fgets() with null pointers is not harder than
avoiding to call it with pointers to invalid memory. Since,
anyway, the programmer has to assure that stream points to a
vaild FILE, he must also assure that it is not NULL. So testing
whether stream is NULL without being able to check whether it
points to a valid FILE is not very useful. Of course, you are
completely free to do that in your fgets() implementation.
--
Army1987 (Replace "NOSPAM" with "email")
If you're sending e-mail from a Windows machine, turn off Microsoft's
stupid “Smart Quotes” feature. This is so you'll avoid sprinkling garbage
characters through your mail. -- Eric S. Raymond and Rick Moen

Sep 7 '07 #23

P: n/a
Keith Thompson <ks***@mib.orgwrites:
>
Yes, such a change could be made, but passing a null pointer to fgets
(or to most standard library functions) is only one of a nearly
infinite number of possible errors. fgets() could detect a null
pointer, but it couldn't reasonably detect all possible invalid
arguments. The burden is on the programmer to avoid passing invalid
arguments; fgets() just has to work properly if it the arguments are
valid.

And if the standard committee decided to require fgets() to behave
reasonably with a null pointer argument, it would be literally decades
before all implementations would conform.
In addition, sometimes two bugs make a feature. If the behaviour changed
over night after a new compile there might be news bugs which could go
days without being discovered in huge legacy code bases. Never
underestimate the knock on effects of changing code libraries. Even if
it is a "one liner".
Sep 7 '07 #24

P: n/a
Army1987 wrote:
On Fri, 07 Sep 2007 12:40:38 +0200, jacob navia wrote:

[snip]
[about checking whether fgets() is called with either s or stream
being NULL or n being nonpositive]
>>>This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.
If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.
No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.

Engineering is a long list of compromises. You have to test what can be
tested and not more but not less.
Avoiding to call fgets() with null pointers is not harder than
avoiding to call it with pointers to invalid memory.
The standard doesn't supply an
bool isvalid_file(FILE *);

This routine would be very easy and cheap to implement
for the folks that wrote the standard library but
it wasn't added to C99.

Then , error checking is very difficult. Still, testing for obvious
bad values such as NULL is feasible and would catch a lot of errors
without just crashing the program.
Since,
anyway, the programmer has to assure that stream points to a
vaild FILE, he must also assure that it is not NULL.
Which programmer? I repeat: this could be a library routine
taht receives the file handle from unknown sources.
So testing
whether stream is NULL without being able to check whether it
points to a valid FILE is not very useful.
Since we can't really check for all possible errors, better
not to check anything.

Sep 7 '07 #25

P: n/a
Richard wrote:
In addition, sometimes two bugs make a feature. If the behaviour changed
over night after a new compile there might be news bugs which could go
days without being discovered in huge legacy code bases. Never
underestimate the knock on effects of changing code libraries. Even if
it is a "one liner".
I can't parse that
If the behaviour changed
over night after a new compile there might be news bugs which could go
days without being discovered in huge legacy code bases.
You mean programs that relied on fgets making a segmentation fault
would now work and that would produce new bugs?

???

Please explain
Sep 7 '07 #26

P: n/a
On Fri, 07 Sep 2007 13:02:27 +0200, jacob navia wrote:
Army1987 wrote:
>On Fri, 07 Sep 2007 12:40:38 +0200, jacob navia wrote:

[snip]
So testing
whether stream is NULL without being able to check whether it
points to a valid FILE is not very useful.

Since we can't really check for all possible errors, better
not to check anything.
Do you think that avoiding to call fgets() with a NULL stream is
any harder than avoiding to call it with an invalid pointer? Do
you think that it is ever possible to do the latter without doing
the former? If fgets() doesn't check whether stream points to a
valid FILE, one must avoid to call it with an invalid pointer.
And if one avoids to call it with an invalid pointer, he/she/it
avoids to call it with a null pointer, almost by definition. And
if one avoids to call it with a null pointer, checking that within
fgets() is useless.
--
Army1987 (Replace "NOSPAM" with "email")
If you're sending e-mail from a Windows machine, turn off Microsoft's
stupid “Smart Quotes” feature. This is so you'll avoid sprinkling garbage
characters through your mail. -- Eric S. Raymond and Rick Moen

Sep 7 '07 #27

P: n/a
"jacob navia" <ja***@jacob.remcomp.frschrieb im Newsbeitrag
news:46**********************@news.orange.fr...
Army1987 wrote:
>On Fri, 07 Sep 2007 12:40:38 +0200, jacob navia wrote:

[snip]
[about checking whether fgets() is called with either s or stream
being NULL or n being nonpositive]
>>>>This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.
If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.

No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.

Engineering is a long list of compromises. You have to test what can be
tested and not more but not less.
Avoiding to call fgets() with null pointers is not harder than
avoiding to call it with pointers to invalid memory.

The standard doesn't supply an
bool isvalid_file(FILE *);

This routine would be very easy and cheap to implement
for the folks that wrote the standard library but
it wasn't added to C99.

Then , error checking is very difficult. Still, testing for obvious
bad values such as NULL is feasible and would catch a lot of errors
without just crashing the program.
Wouldn't someone that calls fgets with a FILE * of NULL be very likely not
to check fgets' returnvalue too?
Then the only sensible thing fgets could do about this is an
assert(stream!=NULL); causing the program to abort right on the spot,
spitting out a more or less usefull diagnostic.

Bye, Jojo
Sep 7 '07 #28

P: n/a
Joachim Schmitz wrote:
"jacob navia" <ja***@jacob.remcomp.frschrieb im Newsbeitrag
news:46**********************@news.orange.fr...
>Army1987 wrote:
>>On Fri, 07 Sep 2007 12:40:38 +0200, jacob navia wrote:

[snip]
[about checking whether fgets() is called with either s or stream
being NULL or n being nonpositive]
>This means 3 integer comparisons in this case. Compared to the
>i/o that fgets is going to do anyway, those 3 integer
>comparisons amount to NOTHING.
If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.
>
No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.

Engineering is a long list of compromises. You have to test what can be
tested and not more but not less.
Avoiding to call fgets() with null pointers is not harder than
avoiding to call it with pointers to invalid memory.
The standard doesn't supply an
bool isvalid_file(FILE *);

This routine would be very easy and cheap to implement
for the folks that wrote the standard library but
it wasn't added to C99.

Then , error checking is very difficult. Still, testing for obvious
bad values such as NULL is feasible and would catch a lot of errors
without just crashing the program.
Wouldn't someone that calls fgets with a FILE * of NULL be very likely not
to check fgets' returnvalue too?
"Someone that calls fgets with a FILE * of NULL"

Yes, that "someone" looks very stupid but all bugs are stupid.
To avoid having software that breaks at the slightest error
with catastrophic failures we should at least try to
establish fail safe procedures at the base of it...
Then the only sensible thing fgets could do about this is an
assert(stream!=NULL); causing the program to abort right on the spot,
spitting out a more or less usefull diagnostic.
Microsoft proposed in their Technical Report a general exception
mechanism. We could use that...
Sep 7 '07 #29

P: n/a
"jacob navia" <ja***@jacob.remcomp.frschrieb im Newsbeitrag
news:46**********************@news.orange.fr...
Joachim Schmitz wrote:
>"jacob navia" <ja***@jacob.remcomp.frschrieb im Newsbeitrag
news:46**********************@news.orange.fr...
>>Army1987 wrote:
On Fri, 07 Sep 2007 12:40:38 +0200, jacob navia wrote:

[snip]
[about checking whether fgets() is called with either s or stream
being NULL or n being nonpositive]
>>This means 3 integer comparisons in this case. Compared to the
>>i/o that fgets is going to do anyway, those 3 integer
>>comparisons amount to NOTHING.
>If you're /serious/ about checking for errors, "3 integer
>comparisions"
>is a substantial underestimate.
>>
No, not in this case. You argument seems to be:
>
If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.
>
Engineering is a long list of compromises. You have to test what can
be
tested and not more but not less.
Avoiding to call fgets() with null pointers is not harder than
avoiding to call it with pointers to invalid memory.
The standard doesn't supply an
bool isvalid_file(FILE *);

This routine would be very easy and cheap to implement
for the folks that wrote the standard library but
it wasn't added to C99.

Then , error checking is very difficult. Still, testing for obvious
bad values such as NULL is feasible and would catch a lot of errors
without just crashing the program.
Wouldn't someone that calls fgets with a FILE * of NULL be very likely
not to check fgets' returnvalue too?

"Someone that calls fgets with a FILE * of NULL"

Yes, that "someone" looks very stupid but all bugs are stupid.
To avoid having software that breaks at the slightest error
with catastrophic failures we should at least try to
establish fail safe procedures at the base of it...
>Then the only sensible thing fgets could do about this is an
assert(stream!=NULL); causing the program to abort right on the spot,
spitting out a more or less usefull diagnostic.

Microsoft proposed in their Technical Report a general exception
mechanism. We could use that...
I'd just prever the program to aport right there. Much better and easier to
debug than to contine with bogus data and corrupted memory which will
eventually lead the program to die at a completly unrelated spot, making it
next to impossible to find the root cause and possible corrupting data
integrity
Sep 7 '07 #30

P: n/a
Joachim Schmitz wrote:
>Microsoft proposed in their Technical Report a general exception
mechanism. We could use that...
I'd just prever the program to aport right there. Much better and easier to
debug than to contine with bogus data and corrupted memory which will
eventually lead the program to die at a completly unrelated spot, making it
next to impossible to find the root cause and possible corrupting data
integrity
Well, by default that mechanism does exactly that.
Abort.

The only difference is that you can "subclass" it
by writing you own function and having that function
called when an error occurs.

Sep 7 '07 #31

P: n/a
On Sep 7, 2:32 pm, Casper H.S. Dik <Casper....@Sun.COMwrote:
Sheth Raxit <raxitsheth2...@gmail.comwrites:
On Sep 7, 1:08 pm, Casper H.S. Dik <Casper....@Sun.COMwrote:
Kenneth Brody <kenbr...@spamcop.netwrites:
However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.
My guess is that this is UB.
Since he's not passing a pointer to a STREAM I'd also say it's UB.
Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.

No. The standard should not make it easier for buggy programs to
blunder on.
Is Assert-ing for NULL is better than Undefined Behaviour ?
Good for Buggy program. Good for platform ?
>
The implementation is doing you a favour by dumping core for this
particular bit of undefined behaviour. You have a bug in your program
(you invoke undefined behaviour, always a bug). If you had continued
onwards, your codee would not have made a distinction between
"file not found" and "file is empty". Perhaps not relevant for you,
but in other cases this might hide a serious bug in the program.

Casper
-Raxit
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

Sep 7 '07 #32

P: n/a
jacob navia wrote:
Chris Dollin wrote:
>jacob navia wrote:
>>Why error analysis is necessary?

Error analysis means trying to have a defined an in all cases
identical reaction to program errors.

This means that for each function we write, we try to
return a specified error report value if things go wrong.

In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.

o Testing for a bad value of n (maximum possible line length)

That would be another integer comparison, but I do not
see immediately where you get this value: "maximum
possible line length"...
From wherever it is.

Actually it's silly of me: even if an implementation has a limit
on the length of line it can deliver, it's perfectly reasonable
to hand it a bigger buffer, ie a larger n. Colour me egg-faced.
>o Testing that the non-null buffer points to a legal C object
containing at least the `n` characters required

o Testing that the non-null stream points to a legal C object

In general, this is impossible
Exactly.
and in the best case it would
repeat in software the tests done by the hardware.
More likely the tests done by other software.
Yes, maybe in some systems this is possible and very cheap.
Unlikely, and that's my point.
But you are just making a caricature of what I said,
No: I'm taking your argument about checking seriously.
a well known way of discussion without being serious.
I'm serious.
>>This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.

If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.
No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
It's not /that/ impossible, and I didn't claim it was impossible.
Consequence:
We do not test anything at all.
That's not my argument.

My argument is that if we're going to talk about the costs of doing
argument checking, let's consider taking argument checking seriously.
(Sticking with C.) We see that the range of options -- and costs -- is
wider than you described.
Engineering is a long list of compromises.
Yes (but not /only/ that).
You have to test what can be tested
No, you don't.

You test what it's /cost-effective/ to have tests for.
and not more but not less.
The question (for fgets) is: is the cost of checking for null/negative
arguments worth the benefit?

You obviously feel that it is. I'm not convinced. I'd be more convinced
in a teaching/debugging implementation of C. If I were worried about
negative sizes or null pointers in my use of fgets, I can always check
them myself, for an overhead comparable to that which fgets itself
would apply -- less, since I can eg move the tests out of the loop.

Maybe it's true that the cost of fgets is utterly dominated by the
I/O it does. But maybe it's true I'm already running at the limits
of my processor and even those paltry three instructions are worth
having.

--
Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Sep 7 '07 #33

P: n/a
jacob navia <ja***@jacob.remcomp.frwrites:
Joachim Schmitz wrote:
<snip>
>Wouldn't someone that calls fgets with a FILE * of NULL be very
likely not to check fgets' returnvalue too?

"Someone that calls fgets with a FILE * of NULL"

Yes, that "someone" looks very stupid but all bugs are stupid.
To avoid having software that breaks at the slightest error
with catastrophic failures we should at least try to
establish fail safe procedures at the base of it...
The idea that fail-safe procedures make software more robust is a huge
can of worms and one the is off topic here anyway.

What is on-topic is the idea that the standard has somehow failed to
be safe by allowing fgets to be undefined when called with NULL as the
stream pointer. That is simply not how C works.

The philosophy of Java and C# may be to push everything you might ever
want into a huge library from which you simply pick the functions you
need, but the philosophy of C is to provide just enough for to write
what you need. The standard library is not, of course, actually
minimal from a formal point of view, but it is not far off. If you
need

char *null_safe_fgets(char *s, int n, FILE *fp)
{
return fp ? fgets(s, n, fp) : NULL;
}

then it is not hard to add it to your toolbox. The C idea -- that you
don't pay for what you don't need, means that programs that already
test for NULL on open (and most will want to do that) can avoid paying
for a test for a NULL stream pointer in the IO operations.

Every non-trivial C project I have been involved with includes a small
library (sometimes only a module) that wraps the IO layer in a set of
primitive operations that suit the task in hand. Often, this can be
borrowed from previous work. It is the C way.

It is possible that this is slightly less common now that we have a
good standard, since one reason for doing it in the past was to
localise all the places where one might have to fiddle about when
porting to new C library. However the idea that you write what you
need on top of a small library is deeply embedded in C.

--
Ben.
Sep 7 '07 #34

P: n/a
Jack Klein wrote:
>
"7.1.4 Use of library functions
1 Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow: If an argument to
a function has an invalid value (such as a value outside the domain of
the function, or a pointer outside the address space of the program,
or a null pointer, or a pointer to non-modifable storage when the
corresponding parameter is not const-qualifed) or a type (after
promotion) not expected by a function with variable number of
arguments, the behavior is undefined."

This makes passing a null pointer to almost all library functions
illegal, without requiring such text in each and every single function
description.
[...]

I knew there had to be something better than 7.19.3p4's reference to
a closed stream. I looked around 7.19's intro on I/O but didn't see
anything about NULL. I didn't think to go all the way back to 7's
intro.

Thanks.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Sep 7 '07 #35

P: n/a
Keith Thompson wrote:
[...]
And if the standard committee decided to require fgets() to behave
reasonably with a null pointer argument, it would be literally decades
before all implementations would conform.
[...]

Well, then they better get off their lazy butts and get cracking!

:-) <--- For the humor-impaired. (And humour-impaired, as well.)

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Sep 7 '07 #36

P: n/a
Sheth Raxit wrote:
Can not it more useful, if standard suggest to returns the NULL, if
stream is NULL., than of Undefined behaviour. ?
By this, every implementation <conforming to standardwill check
if (fgets==NULL) then Instead of Undefined behaviour, it will return
NULL. <or proper error handling.>
No, the stdio implementation is not able to correctly decide
what "proper error handling" should be. When the failure to
open the file is reported to the application by a null-pointer
return from fopen(), the application needs to apply the
proper error recover. In no case would that involve ignoring
the error and proceed to read the non-existent data.
If you fail to open the file, don't try to read from it.
yes,but we are checking currently the behaviour of fgets.
fgets makes no sense when there is no stream for it to read
from. It is quite properly specified as having undefined
behavior in that case. There is no need to require every
conforming C implementation to perform an additional
validity test on standard library parameters every time a
library function is invoked; that would impose a performance
penalty on nearly *every* application, with potential benefit
only for incorrectly coded applications. You are free to use
an implementation that does perform extra validity tests if
you happen to have one. (There are "malloc" libraries like
that.)
Sep 7 '07 #37

P: n/a
/* mystdio.h */
#include <stdio.h> // just for FILE
extern char *myfgets(char *, int, FILE *);
#undef fgets // in case <stdio.hdefined it
#define fgets myfgets
/* ... and others ... */

/* myfgets.c */
#include <stddef.h> // for size_t
#include <stdio.h>
extern void myverify(void *, size_t);
extern void myerror(const char *);
char *myfgets(char *s, int n, FILE *stream) {
if (n < 1)
myerror("n<1");
myverify(s, n - 1); // may invoke myerror
myverify(stream, sizeof(FILE)); // may invoke myerror
return fgets(s, n, stream);
}
Sep 7 '07 #38

P: n/a
Richard Heathfield wrote:
The behaviour of extensions, as far as I'm aware, is not defined by the
Standard, and therefore is covered by the definition of undefined
behaviour, ...
Yes, extensions are allowed that define (necessarily in an
implementation-dependent way) behavior for what the C standard
has labeled as "undefined behavior". Some other kinds of
extensions, such as extensions to the grammar, require at
least one diagnostic to be produced by a conforming C
implementation when a program uses the extension. The
diagnostic could be "Congratulations on making use of some
of our fine extensions!", although I'd hope for something
along the lines "warning: nonstandard extension used".
Sep 7 '07 #39

P: n/a
Sheth Raxit wrote:
Is Assert-ing for NULL is better than Undefined Behaviour ?
Good for Buggy program. Good for platform ?
A failed assert() is generally not a good way of handling an
error, since the application and its supporting libraries are
not given a chance to clean up (flush changes to databases,
etc.). Interrupting the application's procedure in the
middle of some chain of actions could have horrible
consequences. Consider if the error occurs between the
time when the medical equipment starts a pump to inject some
drug into a patient and the time when it stops the pump.

In the case of fgets erroneously called with an invalid
stream pointer, the actual problem is not fgets, it is at an
earlier point in the application where a nonexistent-file
error was not properly handled. Therefore the correct fix
needs to be applied at that earlier point, where suitable
application-controlled steps can be taken to recover from it.
Sep 7 '07 #40

P: n/a
Chris Dollin <ch**********@hp.comwrites:
jacob navia wrote:
[...]
>In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.

o Testing for a bad value of n (maximum possible line length)
[...]

If the system has a maximum possible line length (say, 2000
characters), calling fgets() with n == 3000 is perfectly valid as long
as the buffer is at least 3000 byte long.
o Testing that the non-null buffer points to a legal C object
containing at least the `n` characters required

o Testing that the non-null stream points to a legal C object
Of course these last two may be impossible to check unless the
implementation keep track of *all* objects, which would impose a
tremendous overhead.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 7 '07 #41

P: n/a
Rainer Weikusat <rw*******@mssgmbh.comwrites:
Jonathan Leffler <jl******@earthlink.netwrites:
>Rainer Weikusat wrote:
[...]
>>Any statement ascribing properties to areas not defined by the
C-standard is a statement about something which is not part of C, as
defined by this standard.

Read up on 'Nasal Demons' (Google - 4th entry when I looked). In
comp.std.c land, undefined behaviour means exactly that.

Well, I wasn't about writing 'preferred phantasies of comp.std.c
regulars' but about C. And from the perpsective of the standard text,
claiming that

a = 3;
a = ++a;

results in any particular value for a is as wrong as claiming that it
may cause your next door neighbour to turn into a piano. If it may can
be determined empirically and both the answer and the means for
determining it are not part of the C programming language.
We don't claim (except jokingly) that executing those statements
*will* cause demons to fly out of your nose. The claim is merely that
nasal demons are one of the infinitely many behaviors permitted by the
standard. If you compile and run a program containing those
statements and demons in fact do fly out of your nose, you can
certainly complain to your compiler vendor, but you have no basis for
claiming that the compiler violates the standard.

It's entirely possible that we're sometimes insufficiently precise on
that point.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 7 '07 #42

P: n/a
Rainer Weikusat wrote:
Jonathan Leffler <jl******@earthlink.netwrites:
>>
Read up on 'Nasal Demons' (Google - 4th entry when I looked). In
comp.std.c land, undefined behaviour means exactly that.

Well, I wasn't about writing 'preferred phantasies of comp.std.c
regulars' but about C. And from the perpsective of the standard text,
claiming that

a = 3;
a = ++a;

results in any particular value for a is as wrong as claiming that it
may cause your next door neighbour to turn into a piano.
The standard does indeed not require that UB causes my next door
neighbour to turn into a piano, but that appears to be exactly the
behaviour of my DeathStation 9000.
Are you claiming that this behaviour is not correct?

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
Sep 7 '07 #43

P: n/a
jacob navia wrote:
Jack Klein wrote:
.... snip ...
>>
"7.1.4 Use of library functions
1 Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow: If an argument to
a function has an invalid value (such as a value outside the domain of
the function, or a pointer outside the address space of the program,
or a null pointer, or a pointer to non-modifable storage when the
corresponding parameter is not const-qualifed) or a type (after
promotion) not expected by a function with variable number of
arguments, the behavior is undefined."

Nothing is said about the return value or behavior of any error.
The behavior is UNDEFINED.

Can't you read?

That is what I said!
No you didn't. You quoted something which said a NULL was
returned, without bothering to identify the source of the quote.
Then, in this immediate reply, you got ugly and rude rather than
accepting the accurate correction and a quote from the standard.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Sep 7 '07 #44

P: n/a
jacob navia wrote:
Casper H.S. Dik wrote:
.... snip ...
>>
Dumping core is a good thing; you have a bug, it was caught.
Now go and fix your code.

Casper

Why error analysis is necessary?

Error analysis means trying to have a defined an in all cases
identical reaction to program errors.

This means that for each function we write, we try to
return a specified error report value if things go wrong.

In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.
NULLs are allowed in the receiving buffer, and don't matter since
they will either be beyond the line end or overwritten. It helps
to get the objective right before trying to code for it.

One is also allowed to snip obvious signatures, even though the
originator neglected to include a proper sig. marker. There are no
prizes for extreme laziness or rudeness.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Sep 7 '07 #45

P: n/a
jacob navia wrote:
>
.... snip ...
>
The standard doesn't supply an bool isvalid_file(FILE *);

This routine would be very easy and cheap to implement for the
folks that wrote the standard library but it wasn't added to C99.
No, it isn't easy. This is one more of your silly statements. C
doesn't have files, it has streams. They are controlled by the
FILE type.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Sep 7 '07 #46

P: n/a
CBFalconer wrote:
jacob navia wrote:
>Jack Klein wrote:
... snip ...
>>"7.1.4 Use of library functions
1 Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow: If an argument to
a function has an invalid value (such as a value outside the domain of
the function, or a pointer outside the address space of the program,
or a null pointer, or a pointer to non-modifable storage when the
corresponding parameter is not const-qualifed) or a type (after
promotion) not expected by a function with variable number of
arguments, the behavior is undefined."
Nothing is said about the return value or behavior of any error.
The behavior is UNDEFINED.

Can't you read?

That is what I said!

No you didn't. You quoted something which said a NULL was
returned,
I quoted the standard. That is the "something".
without bothering to identify the source of the quote.

No. I started my message with
>The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
[snip]
>Then, in this immediate reply, you got ugly and rude rather than
accepting the accurate correction and a quote from the standard.
No. I did not insult anyone or whatever. You are dreaming things up.
I just wanted to argument that error checking is lacking in many
functions that *could* reasonably have more error returns specified.

This is a valid opinion, and I am free to argue it.

Sep 7 '07 #47

P: n/a
CBFalconer <cb********@yahoo.comwrites:
jacob navia wrote:
[...]
>In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.

NULLs are allowed in the receiving buffer, and don't matter since
they will either be beyond the line end or overwritten. It helps
to get the objective right before trying to code for it.
[...]

Let's be clear what we're talking about.

Here's the declaration of fgets:

char *fgets(char * restrict s, int n, FILE * restrict stream);

You're interpreting jacob's third point to mean null characters ('\0')
in the array pointed to by 's'. I don't believe that's what he meant;
the initial contents of the array are irrelevant, and if he were
talking about null characters he probably wouldn't have used the term
NULL, which is a macro that expands to a null pointer constant.

I think he was referring to checking in fgets whether s == NULL.
That's a reasonable check to make, but it's not required, and it
misses a plethora of other possible invalid values.

As a programmer, of course, I can't depend on any such checks, since
not all implementations perform them, and that's going to remain the
case for a long time. It's still entirely *my* responsibility to
avoid passing invalid arguments to fgets. If the implementation helps
me out by catching certain errors, that's great (unless it imposes too
much of a burden on *correct* calls), but I can't count on it. If I
don't trust myself to get this right, I can always write a wrapper
that checks the arguments before calling fgets.

A side note: Above I referred to "the array pointed to by 's'". Since
's' is a char*, it doesn't point to an array; it points to a char
(which presumably is the first element of an array). The standard
allows a char* to be a "pointer to a string", but there's no such
wording that allows it to be called a "pointer to an array", since a
pointer to an array is a valid and distinct concept. However, the
standard itself refers to the "the array pointed to by s" (C99
7.19.7.2p2). I suppose it's clear enough from context.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 7 '07 #48

P: n/a
On Sep 7, 5:40 am, jacob navia <ja...@jacob.remcomp.frwrote:
Chris Dollin wrote:
If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.

No, not in this case. You argument seems to be:

If we are going to test exhaustively all errors, that would be
impossible.
Consequence:
We do not test anything at all.
Methinks that is a reasonable stance for an implementor to take.

* Conform to the standard.
* Provide value-adding features like useful and meaningful
diagnostics. Kudos if you can do semantic code analysis at compile
time to detect possible UB at runtime.
* Provide any extensions deemed useful in a way that it doesn't break
anything conforming.

- Anand

Sep 7 '07 #49

P: n/a
In article <87************@fever.mssgmbh.com>,
Rainer Weikusat <rw*******@mssgmbh.comwrote:
>Yes - undefined behaviour means anything can happen,
>This statement is untrue (and obvious nonsense for any conceivable
real-world example). Undefined behaviours is 'behaviour [...] upon
which this international standard imposes no requirements'. This means
whatever the behaviour might or might not be is not relevant for
determining if the implementation is conforming to ISO/IEC 9899:1999,
ie follows the requirements imposed by it, or not.
Ok, let me rephrase it. Undefined behaviour means anything can happen
*without violating the standard*. No real implementation will make
DMR's head explode, but if it did it wouldn't be a standard violation.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Sep 7 '07 #50

285 Replies

This discussion thread is closed

Replies have been disabled for this discussion.