Qry : Behaviour of fgets -- ?

S

Sheth Raxit

This would be redundant and inefficient. Instead of the programmer
checking the return value of fopen() once, all the I/O functions would
have to check the value of the stream every time.

Consider an inner loop calling fgetc(). This is a very simple
operation, probably only about 5-10 instructions most of the time
(because of buffering -- if there's data in the buffer it just has to
copy one byte and increment the buffer pointer). Adding the NULL check
would slow it down by 20-30%, I suspect.
really valid/worth and to the point description. Thanks a lot,

-Raxit
 
R

Richard Tobin

Rainer Weikusat said:
You misunderstand my point. To state that 'the behavious is undefined'
means 'no information regarding this behaviour is available'.

In the context of the C standard, "the behaviour is undefined" doesn't
mean that. It means that no information regarding it is available
*in the C standard*.
This
makes (as I have already written) the claim that 'anything can happen'
as wrong as the claim that 'it will cause global warming to stop'

And given the correct interpretation, that claim is right. The C
standard does not prohibit the implementation from stopping global
warming.

Discussion of nasal daemons and the like is not intended to describe
the real world, it's intended to elucidate a technical term, so
rejecting it on practical grounds is pointless.

-- Richard
 
C

Chris Dollin

Rainer said:
You misunderstand my point. To state that 'the behavious is undefined'
means 'no information regarding this behaviour is available'.

No, it means -- here -- that no restrictions on the behaviour have been
given by the standard.

Although it's just occurred to me to wonder why, say, `i += 1` can't
deliver nasal demons. After all, the Standard only covers the abstract
behaviour of the implementation. An implementation where every addition
operation nasalised you wouldn't be conformant /just because of that/,
would it?
 
B

Ben Bacarisse

Casper H.S. Dik said:
Ben Bacarisse said:
On Sat, 08 Sep 2007 21:48:19 +0200, Army1987 wrote:

]To find out
which we use strchr searching for '\0' which will always succeed. If the
NUL is at buff[size-1] we assume the line is longer than buff.

Doesn't strlen(buf) != size - 1 do the same without looking that
weird?
Or better, set buff[size - 1] to a nonzero value, call fgets, and
check whether buff[size - 1] is zero. This takes O(1) time.
This is a neat solution because it also works in the peculiar case of
a line with embedded nulls.


But does the standard restrict writes to the part of the buffer
where no data was read, i.e., is a standard conforming
implementation allowed to start fgets with:

memset(s, '\0', n);
....

I think not, though there is wriggle room. There is no wriggle room
in the case of no data being read: "[if] no characters have been read
into the array, the contents of the array remain unchanged" so fgets
can't start that way.

Reading one character and then filling with nulls might, just, pass
the other wording but the description is mechanical enough to suggest
the very minimal tampering with the buffer is expected:

"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."
 
K

Kenneth Brody

Rainer said:
(e-mail address removed) (Richard Bos) writes: [...]
but leaves it up to the compiler, and when that compiler does not
care to make sure that that code does something specific but leaves
it up to the accidents of microprocessor behaviour

It is not (generally) possible to execute microprocessor instructions
which don't do something specific. But this speculation is besides the
point. The bheaviours is undefined. This means it is undefined.

You've never run on a CPU which can perform more than one
instruction at a time, have you?

Consider, for example:

int i;
...
i = i++;

There is no reason to expect that the compiler can't generate
something along the lines of:

something \ These two instructions run in parallel
load r1,i /

store r1,i \ As do these
incr i /

This isn't an issue with "j = i++" because the store will write
to j. However, in this case, both instructions attempt to write
to i, causing a bus conflict and locking the system.

Perhaps the system has some protection against this, but it will
still fail depending on the value in i. Perhaps, for example, if
i is 0xffffffff and the increment causes an overflow exception to
occur while it is handling the collision exception.

Okay, I suppose you could say that this behavior is "defined" in
the sense that the outcome is not dependent on quamtum physics,
but it's still not "defined" in the sense that "the answer must
be A or B". (There are many people who stongly believe that the
only possible outcome of "i=3; i=i++;" is that i must contain the
value 3, and there are others who know about sequence points who
will insist that the only possible answers are that i contain the
value 3 or 4.)

And, regardless, the behavior is still "undefined" as far as the
C standard is concerned. Code that depends on a particular
compiler's particular code generator's output is asking for
trouble.

--
+-------------------------+--------------------+-----------------------+
| 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

CBFalconer said:
That depends. Is he in tune? :)

He's tuned a little high. That middle C sounds like a C#. :)

--
+-------------------------+--------------------+-----------------------+
| 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

kuyper

Richard said:
Charlie Gordon said:


Probably misplaced zeal. The Rationale explains that it's to promise the
compiler that s and stream are not aliaseseseses of each other. Um,
yes, okay, er... fine.

I'm not sure I follow the "misplaced zeal' comment. Do you really want
the standard to say that fgets() must behave as described, even if s
happens to alias stream? The purpose for which 'restrict' was invented
was to convey the fact that such situations are to be avoided.
 
R

Rainer Weikusat

Kenneth Brody said:
Rainer said:
(e-mail address removed) (Richard Bos) writes: [...]
but leaves it up to the compiler, and when that compiler does not
care to make sure that that code does something specific but leaves
it up to the accidents of microprocessor behaviour

It is not (generally) possible to execute microprocessor instructions
which don't do something specific. But this speculation is besides the
point. The bheaviours is undefined. This means it is undefined.

You've never run on a CPU which can perform more than one
instruction at a time, have you?

Would you please stop bombarding me with this trash? I am not trying
to argue for the standpoint you would like to impose onto me and if
you haven't understood that by now, the chances that you ever will are
slim.

So leave it.
 
K

kuyper

Rainer Weikusat wrote:
....
You misunderstand my point.

No, we understand your point, which is how we realized that it's in
need of correction.
... To state that 'the behavious is undefined'
means 'no information regarding this behaviour is available'.

That might be what the phrase means in ordinary English; it's not
what the phrase means in the C standard. The C standard explicitly
defines "undefined behavior" as referring to "behavior ... upon which
THIS INTERNATIONAL STANDARD imposes no requirements" (emphasis
added). You yourself have quoted this text, but seem to have
forgotten the significance of the part that I emphasized: it means
that the behavior is undefined, as far as the standard is concerned,
even if something other than the standard does provide a definition..
Within the context of the C standard, that's what the phrase means;
it's meaning in ordinary English is irrelevant.

That's a pretty good thing because if the standard used your
definition of "undefined behavior" it would require implementors to
detect code which has undefined behavior (which is currently not
required, and infeasible because in some cases it's equivalent to
solving the halting problem). Implementations would have to make sure
that it's impossible to collect any information about what the actual
behavior would be when the behavior is undefined. I don't see any way
for a compiler to render such data collection impossible. In
particular, I don't see any way the implementation can prevent
collection of the following information about the behavior: "the
behavior will be consistent with physical law". Therefore, I'm glad
that the standard doesn't mandate the hiding of such information.
... This
makes (as I have already written) the claim that 'anything can happen'
as wrong as the claim that 'it will cause global warming to stop' or
'nothing will happen' or 'it will cause a to be incremented twice' or
any other conceivable description of any something.

There's a big difference between stating that some particular thing
must happen (which is a direct contradiction of the idea that the
behavior is undefined), and stating that some particular thing may
happen (which is an explicit example of precisely the same idea that
is conveyed by the phrase "undefined behavior"). I can't figure out
your reasoning that leads you to see "As far as the standard is
concerned, such code may cause nasal deamons" as contradictory to
either your definition of "undefined behavior", or the standard's
definition. With your definition, it's quite clear that there's no
information allowing you to reject nasal daemons as a possible
outcome, With the standard's definition, it's clear that the standard
contains no wording which forbids nasal daemons as an outcome. The
only difference is that the standard's definition allows reality to
impose a constraint due to the non-existence of nasal deamons. Your
definition would mandate that the implementation must ensure that
nasal daemons are a possibility, whether or not reality cooperates.
As soon as you (or anyvbody else) claims that such-and-such a thing
may happen, you are not talking about C anymore.

I don't see how you can reach that conclusion - the most plausible
interpretation I can come up with which makes that a reasonable
conclusions is that you are confusing "may" with "must", but that
doesn't seem very plausible either. Saying that "anything can happen"
is a valid way of restating the fact the the C standard fails to
impose any requirements on the behavior. Saying that some particular
thing "may happen" provides a specific example of what "anything may
happen" means, and it's useful didactically because well chosen
examples of behavior that is not prohibitied help motivate developers
to avoid writing code with undefined behavior.
 
R

Richard Heathfield

kuyper said:
I'm not sure I follow the "misplaced zeal' comment. Do you really want
the standard to say that fgets() must behave as described, even if s
happens to alias stream? The purpose for which 'restrict' was invented
was to convey the fact that such situations are to be avoided.

I'm just trying to imagine what kind of bozo would alias a data buffer
with a stream pointer.

Um, yeah, okay, maybe it's not so hard to imagine. Sturgeon and all
that. I retract the "misplaced".
 
C

Charlie Gordon

Richard Heathfield said:
Charlie Gordon said:


Probably misplaced zeal. The Rationale explains that it's to promise the
compiler that s and stream are not aliaseseseses of each other. Um,
yes, okay, er... fine.

That's what I was inferring, is the Rationale available for download ?

restrict is basically a promise by the programmer to the compiler that the
parts of objects read and modified by restrict-qualified pointers do not
overlap.
Specifying restrict on arguments in function prototypes gives no indication
to the compiler, and only a vague hint to the programmer, quite insufficient
to avoid undefined behaviour or to generate appropriate warnings.

Why should the compiler complain about the following:
char buf[100];
memcpy(buf, buf + 10, 10); // both pointers point to the same object, but
the data accessed thru them do not overlap.
memcpy(buf, buf, 0); // pointers are identical! yet behaviour is defined, no
data is accessed.

What about this example:
const char *modestr = "r";
FILE *fp = fopen(modestr, modestr);

What is wrong with that code ? why does fopen specify restrict on its const
char * parameters ? why should aliassing be a problem in this case as
neither string is modified ?
It looks like unnecessary noise for no benefits.
 
C

Charlie Gordon

Richard Heathfield said:
kuyper said:


I'm just trying to imagine what kind of bozo would alias a data buffer
with a stream pointer.

Um, yeah, okay, maybe it's not so hard to imagine. Sturgeon and all
that. I retract the "misplaced".

Still not a good reason to pollute the library spec with useless restrict
keywords:

fread(stdin, sizeof(*stdin), 1, stdin); invokes undefined behaviour and
could be detected because of the restrict qualification.... but
fread(stdout, sizeof(*stdout), 1, stdin); is just as bad and will go
unnoticed ;-)
 
D

Douglas A. Gwyn

Rainer said:
... But any example of "behaviour" is necessarily
defined and not undefined.

No, in many cases C-standard "undefined behavior" has no definition
anywhere and is in generally unpredictable. For example, what
happens when you pass a pointer to a random place instead of a
valid FILE object to a stdio function? Almost anything could
happen, depending on what happens to be stored at that location.

The point about "undefined behavior" is to completely avoid
producing it in maximally portable code, and to follow local
implementation guidelines when the implementation chooses to
provided a definition for specific cases of behavior that the
C standard labels "undefined".
 
K

Kenneth Brody

Charlie said:
Not a surprise: he lives in the D flat.

Ask a joke writer, you're a natural. Such things are not my forte,
but I won't rest until I can coda response that will make you quaver
in anticipation.

--
+-------------------------+--------------------+-----------------------+
| 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]>
 
D

Douglas A. Gwyn

Charlie said:
Specifying restrict on arguments in function prototypes gives no indication
to the compiler, and only a vague hint to the programmer, quite insufficient
to avoid undefined behaviour or to generate appropriate warnings.

It did allow us to not put in all those extra chunks of wording
saying that the pointed-to objects shall not overlap.
 
B

Bart van Ingen Schenau

Rainer said:
I claim that this behaviour is highly illegal and would suggest that
you should try to get a different computer. Apart from that, since no
(standard) definition of 'correct behaviour' exists for this
particular case, its 'correctness' cannot be argued about without
refering to some definition of 'correct behaviour' which is not the
C-standard.

You seem to contradict yourself. If the correctness of the behaviour can
not be determined from the C standard, then you also can not claim that
any particular behaviour is incorrect for the DS9K.

Please not that the DS9K does not always obey the laws of physics, so
behaviour that ranges from physically implausible to impossible can
very well occur with a DS9K.
If you are not familiar with the DS9K, take a look here
http://en.wikipedia.org/wiki/DeathStation_9000, and at some of the
linked pages.

Bart v Ingen Schenau
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Bart said:
Please not that the DS9K does not always obey the laws of physics,

Either the DS9K obeys the laws of physics, or you don't have a DS9K. Choose
one.
 

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

Forum statistics

Threads
474,098
Messages
2,570,623
Members
47,236
Latest member
EverestNero

Latest Threads

Top