Qry : Behaviour of fgets -- ?

K

Kenneth Brody

Jack said:
"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:[email protected]>
 
K

Kenneth Brody

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:[email protected]>
 
R

Richard Tobin

Kenneth Brody said:
But, what if your particular implementation does document the
behavior? Yes, as far as the Standard is concerned, it's UB,
but have you really invoked UB on that particular platform?

Yes - undefined behaviour means anything can happen, and the thing
that's happened is the behaviour defined by the implementation.
Behaviour undefined by the standard has been invoked on that platform,
even though it is defined by the implementation.

-- Richard
 
R

Richard Heathfield

Kenneth Brody said:
The Standard does not
require any implementation to document the behaviour of:

unsigned char *p = (unsigned char *)0xb8000000UL;
*p++ = 'A';
*p++ = 0x84;
[...]

But, what if your particular implementation does document the
behavior? Yes, as far as the Standard is concerned, it's UB,
but have you really invoked UB on that particular platform?

Yes, as far as the Standard is concerned. In comp.lang.c, that's what
counts. (I note that this is c/p'd to c.u.p., where they might have a
different opinion!)
 
R

Rainer Weikusat

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.

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.
 
D

Douglas A. Gwyn

Sheth said:
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 standard> will 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.
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.)
 
D

Douglas A. Gwyn

/* mystdio.h */
#include <stdio.h> // just for FILE
extern char *myfgets(char *, int, FILE *);
#undef fgets // in case <stdio.h> defined 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);
}
 
D

Douglas A. Gwyn

Richard said:
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".
 
D

Douglas A. Gwyn

Sheth said:
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.
 
J

Jonathan Leffler

Rainer said:
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.

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. You invoke it,
and if the program erases every file on your system, there is nothing in
the standard that says "that was the incorrect response to undefined
behaviour". As a QoI (Quality of Implementation) issue, you might be
legitimately chagrined and decide to (a) change compilers and (b) be
more careful, but the ISO C Standard does not say that was the wrong
response to invoking undefined behaviour.
 
R

Rainer Weikusat

Jonathan Leffler said:
Rainer said:
But, what if your particular implementation does document the
behavior? Yes, as far as the Standard is concerned, it's UB,
but have you really invoked UB on that particular platform?
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.
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.
 
K

Keith Thompson

Chris Dollin said:
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.
 
K

Keith Thompson

Rainer Weikusat said:
Jonathan Leffler said:
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.
 
C

CBFalconer

jacob said:
Jack Klein wrote:
.... snip ...

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.
 
B

Bart van Ingen Schenau

Rainer said:
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
 
C

CBFalconer

jacob said:
Casper H.S. Dik wrote:
.... snip ...

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.
 
C

CBFalconer

jacob said:
.... 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.
 
K

kuyper

Kenneth said:
Richard said:
Casper H.S. Dik said:


No. Implementation-defined behaviour is behaviour that the Standard
requires the implementation to document. The Standard does not require
any implementation to document the behaviour of:

unsigned char *p = (unsigned char *)0xb8000000UL;
*p++ = 'A';
*p++ = 0x84;
[...]

But, what if your particular implementation does document the
behavior? Yes, as far as the Standard is concerned, it's UB,
but have you really invoked UB on that particular platform?

UB is not "invoked"; that wording carries with it the concept that
there's a particular kind of behavior that is labelled by "UB", and
that using C in the wrong way allows that kind of behavior. That
concept is almost, but not exactly, opposite to the correct way of
thinking about UB.

The correct statement is that such code has behavior that is not
defined by the C standard; a situation which the C standard quite
reasonably labels as "undefined behavior". However, just because
that's the C standard's jargon for such code, doesn't mean that the
behavior is necessarily undefined in the ordinary English sense of the
phrase. The behavior may be perfectly well-defined - by something
other than the C standard. It could be defined by the POSIX standard,
or it could be defined by the particular implementation of C that
you're using, or something else entirely.

Definitions of the behavior which are provided by other sources than
the C standard are off-topic in comp.std.c; I'm not sure about the
policies of the other newsgroups this message is cross-posted to.
However, just because such behavior is off-topic doesn't mean that
it's meaningless, or non-existent, or not worth talking about, as some
other people have implied. It's just not appropriate to talk about
them in comp.std.c.
 
J

jacob navia

CBFalconer 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.
 
J

jacob navia

Rainer said:
Jonathan Leffler said:
Rainer said:
(e-mail address removed) (Richard Tobin) writes:
But, what if your particular implementation does document the
behavior? Yes, as far as the Standard is concerned, it's UB,
but have you really invoked UB on that particular platform?
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.
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.

Please keep in mind that comp.std.c has other people than those
'regulars'. Do not generalize.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,087
Messages
2,570,600
Members
47,222
Latest member
jspanther

Latest Threads

Top