clrscr and UB 
Author Message
 clrscr and UB

The discussion has been raging over the issue of UB.  It stemmed from the
following dialog:

OP [trimmed]:

Quote:
> #include <stdio.h>
> #include <dos.h>
> #include <conio.h>

> void main()
> {
>  int i,valid,coins,coin_total=0;
>  int coin_amt[64],call_time;
>  char c,call_type,phone_num[64];
>  valid = 0;

>  while (valid == 0)
>  {
>   clrscr();

Initial response [trimmed]:

Quote:
> Non-standard function invokes undefined behaviour.

That is, the respondent suggests that calling the non-standard function
"clrscr" invokes undefined behaviour.

It is my contention that this is at best an unsupportable position, and
at worst, a complete load of hooie.  Here's why.

First, the quotation from the standard, as provided by "Pete":

* Undefined behavior --- behavior, upon use of a nonportable or
   erroneous program construct, of erroneous data, or of
   indeterminately-valued objects, for which the Standard imposes no
   requirements.  Permissible undefined behavior ranges from ignoring
   the
   situation completely with unpredictable results, to behaving during
   translation or program execution in a documented manner
   characteristic
   of the environment (with or without the issuance of a diagnostic
   message), to terminating a translation or execution
   (with the issuance of a diagnostic message).
   If a ``shall'' or ``shall not'' requirement that appears outside of
   a constraint is violated, the behavior is undefined.  Undefined
   behavior is otherwise indicated in this Standard by the words
   ``undefined behavior'' or by the omission of any explicit definition
   of behavior.  There is no difference in emphasis among these three;
   they all describe ``behavior that is undefined.''

The key points here are:

 The use of:
   non-portable construct
   erroneous construct
   erroneous data
   intederminately-valued objects

 Violation of a "shall" or "shall not" requirement, outside of a
 constraint

 Anywhere the standard specifically states "undefined behaviour"

Now, let's examine the situation.  First, let's put our ducks in a row.
Very few C99 compilers exist, and the vast majority of code being
written, today, is for C89 compilers.  I think we can safely assume we
are, in fact, going to be dealing with a C89 compiler.  If nothing else,
I would think that the lack of the implicit int rule in C99 would mandate
a prototype in scope for clrscr(), but that's, really, not a very
interesting case.  C89 provides a little more for examination.

In C89, the function clrscr, as used above, returns an int and takes
either an unspecified number of arguments or zero arguments - I don't
recall offhand if the calling of it once with zero parms is sufficient to
require subsequent invocations to require zero or not... not that it
really matters here.

The key point here is that, barring an incompatible definition of the
function, it should behave as int clrscr(), and the OP is ignoring the
return value, if any.

So the question is, how to determine if it does, in fact, invoke UB?
Let's see.

First, we don't know what return type the function has, so we can't know
if there's any UB in terms of stuffing some incompatible data type (or,
for that matter, the "return value" of a void function) into an int.
There could be, but we don't know either way, so we can't say that this
aspect of calling the function invokes UB.

Second, we don't know if there's an incompatibility between what parms
the function expects, and what we're passing it; it may well not expect
any, so we doon't know either way - and we can't say that UB is invoked
for that reason.

Third, as far as I can tell, the function name doesn't invade any
reserved spaces or otherwise violate any rules, and it appears that,
apart from unknown incompatibilities in return type or parameter lists,
it is, in fact, being called correctly.  That is, simply using it the way
it is used does not seem to invoke any UB.

What we're left with, then, is the conclusion that any UB _must_ be in
the body of the function itself.

Now, it's possible that, in some cases, we could determine that the
function in question is, indeed, going to invoke UB somehow.  If the
comment for a function described it as "Plays the Minute Waltz by writing
memory-mapped registers for the Whositz sound card" we could be
reasonably certain that it invoked at least some sort of UB - since it
would presumably be writing to areas of memory it hadn't actually
allocated (or provided non-allocated objects for).

Not so in this case, there's no comments.  Oh, we can guess that it
probably clears the screen, but for all we actually know for certain, it
may simply set an int value to zero, or some other equally trivial
operation.

So how do we tell if UB is invoked?  Simple: we look at the code.

Does the code use non-portable constructs?  We don't know.  [1]
Does the code use erroneous constructs?  We don't know.
Does the code use erroneous data?  We don't know.
Does the code use intedterminately-value objects?  We don't know.
Does the code violate a "shall" or "shall not" requirment, outside of a
constraint?  We don't know.
Does the standard specifically mention clrscr, and slap a comment of
"undefined behaviour" on it?  No.

That's six separate tests.  Of the six, five tell us we can't answer the
question, and the sixth says that if all the rest could be answered "no",
then the function wouldn't invoked undefined behaviour.

What we're left with, then, is five questions.  If the answer to any of
them is "yes", then the function invokes UB.

So, _is_ the answer to any of the five questions "yes"?  No.  The answer
to all five is "We don't know."

It follows, then, that we _cannot_ state, with any degree of validity,
that, as the respondant suggested, "Non-standard function invokes
undefined behaviour."  At most we can say "Non-standard function _may_
invoke undefined behaviour" but that's true of _any_ function - even
those mandated by the standard - if there's a bug of some sort.  The
notion that a function _may_ invoke UB is trivial; we can ignore it,
since the question isn't whether using this function _may_ invoke UB, but
whether or not it _does_ invoke UB.

In summation, from what has been discussed so far, there is absolutely no
possible way the respondant could have concluded that calling the
function in question did, indeed, invoke undefined behaviour.  He may
suspect it does, he may even have perfectly good reasons for suspecting
it does - but he cannot in actuality know it.

As yet, despite the lengthy discussions, none of the supporters of the
proponent's position has in fact been able to answer any of those five
questions about the code, since they weren't provided with the code - nor
does it seem likely they will be able to answer those questions.
Further, none of them have been able to show an actual error in the
invocation of the function, so neither the body of the function nor its
invocation have been shown to invoke UB.

Therefore, the assessment that the use of the function invokes UB, at
least until it is demonstrated to invoke UB, is not a supported argument,
and should be disregarded.

Responses which can demonstrate, without ever seeing the code, that the
code does, indeed, violate one of the five relevant points, are welcomed.
Further "is too" style posts would seem to not provide any value, since
"is too" is not particularly useful in establishing the validity of the
case.  Post what you will, but really, simply rehashing the current lot
of arguments, not a one of which has even come close to making any sort
of actual relevant point, seems to be simply a waste of bandwidth.

[1] No, the use of the name "clrscr" does not appear to be a non-portable
construct.  That is, were the code for clrscr provided, barring actual
non-portable constructs _within_ the function, there's no reason to
suspect the code couldn't be compiled by any conforming implementation;
the fact the source to the function isn't included is no more significant
in this discussion than the fact that bits of code are often elided for
brevity - usually resulting in non-compilable program snippets but
providing clearer context of the actual problem.



Thu, 22 Jul 2004 16:40:16 GMT  
 clrscr and UB
I am going to change the name of the function here temporarily;
let us say that, despite the subject line above, the function is
just plain "f()".



Quote:
>In C89, the function [f()] as used above, returns an int and takes
>either an unspecified number of arguments or zero arguments - I don't
>recall offhand if the calling of it once with zero parms is sufficient to
>require subsequent invocations to require zero or not... not that it
>really matters here.

Assuming function f() is written in strictly conforming C89 code,
the lack of any declaration in C9 does indeed cause an implicit
definition.  This implicit definition gives it a type that is
type-compatible with any call of any number of arguments, so no
diagnostic is required even if we write:

    f();
    f(1);
    f("hello");
    f("world", 3L);

all in a row.  However, if f() *is* written in strictly conforming
C89 code, its actual definition must have a fixed number of arguments
(possibly zero), and all of those arguments must have a type that
is already "fully wide" so that the implicit argument widening does
not change them.  Any such definition for f() that would render
the first call fully-defined would render the remaining three calls
undefined; any such definition for f() that would render the second
call fully-defined would render the remaining undefined; and so
on.

In other words, a "nice" compiler probably "ought to" complain
about these calls.  No diagnostic is required, however, and the
pragmatic C-code-writer will provide a prototype so as to force
diagnostics for the three (or all four, as the case may be) incorrect
calls.  To put it more crudely: always use prototypes; they may
save your butt.

Anyway:

Quote:
>The key point here is that, barring an incompatible definition of the
>function, it should behave as [int f()], and the OP is ignoring the
>return value, if any.

>So the question is, how to determine if it does, in fact, invoke UB?

[snipped long version; here is my shorter version of the answer.]

We must see the source for f(), and all the functions that f()
calls.  If we cannot see that, we have only one other place to
look: the C89 standard.  If the behavior of f() is not directly
defined in the C standard, and the source code for f() is not
ultimately visible, we have undefined behavior.  If the source code
for f() is visible but it contains calls to some function g(), the
process repeats: either g() is defined in the C89 standard, or we
must see g()'s source code.

After applying this rule recursively, we will either have defined
behavior (possibly including implementation-defined behavior within
f()), or undefined behavior.  There are no shades of grey; there
are only times when we do not yet know the answer (and therefore
should be careful, lest it turn out to be "yes, there is undefined
behavior").

Quote:
>In summation, from what has been discussed so far, there is absolutely no
>possible way the respondant could have concluded that calling the
>function in question did, indeed, invoke undefined behaviour.

Indeed.  Instead of saying "this produces undefined behavior", the
100%-perfect comp.lang.c answer is: "you will have to show me the
source to function f() too, and perhaps additional source files."

In this particular case, of course, the name is not f(), but rather
a better-known one:

Quote:
>He may suspect it does, he may even have perfectly good reasons for
>suspecting it does - but he cannot in actuality know it.

Not in comp.lang.c, indeed.  Outside comp.lang.c -- if for instance
the original poster cross-posted to groups X and Y, meaning he had
something that only people who care about *both* X *and* Y should
see (this is a bug in most newsreaders) :-) -- that "external
knowledge" may filter in.  And of course, since people *are* people,
you should not expect perfection.  Outside knowledge *will* leak
in.  Those who know that most clrscr()s that people actually use
do in fact use, at some point, some amount of undefined behavior,
should probably be forgiven for not forgetting it here. :-)
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)





Thu, 22 Jul 2004 20:38:13 GMT  
 clrscr and UB
On Sunday, in article


Quote:
>The discussion has been raging over the issue of UB.  It stemmed from the
>following dialog:

>OP [trimmed]:

>> #include <stdio.h>
>> #include <dos.h>
>> #include <conio.h>

>> void main()
>> {
>>  int i,valid,coins,coin_total=0;
>>  int coin_amt[64],call_time;
>>  char c,call_type,phone_num[64];
>>  valid = 0;

>>  while (valid == 0)
>>  {
>>   clrscr();

>Initial response [trimmed]:

>> Non-standard function invokes undefined behaviour.

>That is, the respondent suggests that calling the non-standard function
>"clrscr" invokes undefined behaviour.

In the context of standard C, yes it does.

Quote:
>It is my contention that this is at best an unsupportable position, and
>at worst, a complete load of hooie.  Here's why.

Any position that requires the standard to limit the possibilities of
behaviour for code that the standard has no control over is what
would be unsupportable.

- Show quoted text -

Quote:
>First, the quotation from the standard, as provided by "Pete":

>* Undefined behavior --- behavior, upon use of a nonportable or
>   erroneous program construct, of erroneous data, or of
>   indeterminately-valued objects, for which the Standard imposes no
>   requirements.  Permissible undefined behavior ranges from ignoring
>   the
>   situation completely with unpredictable results, to behaving during
>   translation or program execution in a documented manner
>   characteristic
>   of the environment (with or without the issuance of a diagnostic
>   message), to terminating a translation or execution
>   (with the issuance of a diagnostic message).
>   If a ``shall'' or ``shall not'' requirement that appears outside of
>   a constraint is violated, the behavior is undefined.  Undefined
>   behavior is otherwise indicated in this Standard by the words
>   ``undefined behavior'' or by the omission of any explicit definition
>   of behavior.  There is no difference in emphasis among these three;
>   they all describe ``behavior that is undefined.''

>The key points here are:

> The use of:
>   non-portable construct
>   erroneous construct
>   erroneous data
>   intederminately-valued objects

> Violation of a "shall" or "shall not" requirement, outside of a
> constraint

> Anywhere the standard specifically states "undefined behaviour"

"Or by the omission of any explicit definition of behavior".

- Show quoted text -

Quote:
>Now, let's examine the situation.  First, let's put our ducks in a row.
>Very few C99 compilers exist, and the vast majority of code being
>written, today, is for C89 compilers.  I think we can safely assume we
>are, in fact, going to be dealing with a C89 compiler.  If nothing else,
>I would think that the lack of the implicit int rule in C99 would mandate
>a prototype in scope for clrscr(), but that's, really, not a very
>interesting case.  C89 provides a little more for examination.

>In C89, the function clrscr, as used above, returns an int and takes
>either an unspecified number of arguments or zero arguments - I don't
>recall offhand if the calling of it once with zero parms is sufficient to
>require subsequent invocations to require zero or not... not that it
>really matters here.

>The key point here is that, barring an incompatible definition of the
>function, it should behave as int clrscr(), and the OP is ignoring the
>return value, if any.

However the standard satys nothing about how clrscr() is defined, if
at all. It might be with a float return type and if we call it as
having an int return type then we get, you guessed it undefined
behaviour.

Quote:
>So the question is, how to determine if it does, in fact, invoke UB?
>Let's see.

>First, we don't know what return type the function has, so we can't know
>if there's any UB in terms of stuffing some incompatible data type (or,
>for that matter, the "return value" of a void function) into an int.
>There could be, but we don't know either way, so we can't say that this
>aspect of calling the function invokes UB.

As long as there is the possibility of undefined behaviour we have
no guarantees about how it will be have, i.. it has undefined behaviour.

Quote:
>Second, we don't know if there's an incompatibility between what parms
>the function expects, and what we're passing it; it may well not expect
>any, so we doon't know either way - and we can't say that UB is invoked
>for that reason.

Again, that is the only thing we can say.

- Show quoted text -

Quote:
>Third, as far as I can tell, the function name doesn't invade any
>reserved spaces or otherwise violate any rules, and it appears that,
>apart from unknown incompatibilities in return type or parameter lists,
>it is, in fact, being called correctly.  That is, simply using it the way
>it is used does not seem to invoke any UB.

>What we're left with, then, is the conclusion that any UB _must_ be in
>the body of the function itself.

>Now, it's possible that, in some cases, we could determine that the
>function in question is, indeed, going to invoke UB somehow.  If the
>comment for a function described it as "Plays the Minute Waltz by writing
>memory-mapped registers for the Whositz sound card" we could be
>reasonably certain that it invoked at least some sort of UB - since it
>would presumably be writing to areas of memory it hadn't actually
>allocated (or provided non-allocated objects for).

>Not so in this case, there's no comments.  Oh, we can guess that it
>probably clears the screen, but for all we actually know for certain, it
>may simply set an int value to zero, or some other equally trivial
>operation.

>So how do we tell if UB is invoked?  Simple: we look at the code.

The problem is that we don't have the code.

Quote:

>Does the code use non-portable constructs?  We don't know.  [1]
>Does the code use erroneous constructs?  We don't know.
>Does the code use erroneous data?  We don't know.
>Does the code use intedterminately-value objects?  We don't know.
>Does the code violate a "shall" or "shall not" requirment, outside of a
>constraint?  We don't know.
>Does the standard specifically mention clrscr, and slap a comment of
>"undefined behaviour" on it?  No.

The bottom line is that clrscr() has undefined behaviour because the
standard doesn't contain any definition of behaviour for it.

Quote:
>That's six separate tests.  Of the six, five tell us we can't answer the
>question, and the sixth says that if all the rest could be answered "no",
>then the function wouldn't invoked undefined behaviour.

In none of those tests can we constrain the behaviour of the function
clrscr(). The only possible conclusion from each and every one of those
tests is that the function has undefined behaviour.

Quote:
>What we're left with, then, is five questions.  If the answer to any of
>them is "yes", then the function invokes UB.

No, if there is even the slightest possibility that the behaviour is
unconstrained then the standard makes no requirement about what will
happen and we have undefined behaviour. Put it this way: is there
any limitation on what clrscr() can do while still being part of a
conforming implemtation? The answer is no. Total lack of limitation
is called undefined behaviour.

Quote:
>So, _is_ the answer to any of the five questions "yes"?  No.  The answer
>to all five is "We don't know."

Which is enough.

...

Quote:
>As yet, despite the lengthy discussions, none of the supporters of the
>proponent's position has in fact been able to answer any of those five
>questions about the code, since they weren't provided with the code - nor
>does it seem likely they will be able to answer those questions.

The point is that an answer of "maybe" to those questions is enough
to give undefined behaviour. Only a categorical "no" can avoid it.
If you want to prove that the function does not invoke undefined
behavour then you must prove that that the answer to each and every one
of those questions is "no", and others as well.

Quote:
>Further, none of them have been able to show an actual error in the
>invocation of the function, so neither the body of the function nor its
>invocation have been shown to invoke UB.

You don't have to prove that there is an error, you have to prove that
there can be an error.

...

Quote:
>[1] No, the use of the name "clrscr" does not appear to be a non-portable
>construct.  That is, were the code for clrscr provided, barring actual
>non-portable constructs _within_ the function, there's no reason to
>suspect the code couldn't be compiled by any conforming implementation;
>the fact the source to the function isn't included is no more significant
>in this discussion than the fact that bits of code are often elided for
>brevity - usually resulting in non-compilable program snippets but
>providing clearer context of the actual problem.

The lack of source code to clrscr() is absolutely key to the argument.
With it you might be able to prove that the fucntion is well-defined
according to the standard. Without it that is impossible.

Note that the fact that a function has undefined behaviour in the
context of standard C dosn't mean tha it has undefined behaviour
in a different context. For example functions like open() are undefined
in a standard C environment but are well defined in a POSIX environment.

--
-----------------------------------------


-----------------------------------------



Thu, 22 Jul 2004 19:33:06 GMT  
 clrscr and UB
[snips]

Quote:

>> Anywhere the standard specifically states "undefined behaviour"

> "Or by the omission of any explicit definition of behavior".

The functionality of a piece of code may be perfectly well defined, but
if you haven't got the code, you can't _know_ that it is well defined, so
all you have is an unknown - not necessarily undefined behaviour.  To
then say "must be UB" is an incorrect conclusion.

Quote:
>>The key point here is that, barring an incompatible definition of the
>>function, it should behave as int clrscr(), and the OP is ignoring the
>>return value, if any.

> However the standard satys nothing about how clrscr() is defined,

Wrong; the standard may _well_ say many things about how clrscr is
defined, insofar as it has many things to say about how functions, in
general are defined; that is, it defines what conforming code can and
cannot do, and if the code for clrscr is conforming code, its behaviour
is, in fact, defined.

The fact that the standard doesn't explicitly mention clrscr is
irrelevant; the standard doesn't mention any of the function names I
create, but that doesn't mean my creating those names, or the code behind
the function names, involves UB; it simply means that the naming of the
function, except in cases where the name violates reserved spaces, is
irrelevant; what matters is what the code does.  Now either my functions
invoke UB as a result of bad code, or they don't - but if you don't have
the code in front of you, you don't know either way.

Quote:
> all. It might be with a float return type and if we call it as having an
> int return type then we get, you guessed it undefined behaviour.

It might, but since we don't know that, we can't conclude that it does,
in fact, invoke UB.  We can say it _might_ invoke it, but we can't say
that it _does_ invoke it.

Quote:
>>First, we don't know what return type the function has, so we can't know
>>if there's any UB in terms of stuffing some incompatible data type (or,
>>for that matter, the "return value" of a void function) into an int.
>>There could be, but we don't know either way, so we can't say that this
>>aspect of calling the function invokes UB.

> As long as there is the possibility of undefined behaviour we have no
> guarantees about how it will be have, i.. it has undefined behaviour.

Not at all.  You're failing to grasp a very simple concept: that you, as
an individual, do not encompass the totality of the universe.

If I were to write a function, call it clrscr, and very carefully check
it to ensure it invoked UB, then it wouldn't invoke UB.  If I fail to
provide you with a copy of the source code - because I've elided it for
brevity, perhaps, or I've provided a library but not the sources - that
doesn't make the source code magically transform from well-defined to
undefined; the code _remains_ well defined, all that's changed is whether
the person being exposed to the function happens to _know_ that or not.

So too with clrscr.  Either the code invokes UB, or it doesn't.  Since we
don't have the code, all we can do is guess.  If it, in fact, is
well-defined code, the fact that we don't happen to _have_ the code
doesn't render it UB; it simply means we don't know what, if anything,
the code does, or how, or if it's well-defined or not.

Quote:
>>Second, we don't know if there's an incompatibility between what parms
>>the function expects, and what we're passing it; it may well not expect
>>any, so we doon't know either way - and we can't say that UB is invoked
>>for that reason.

> Again, that is the only thing we can say.

No, we can say "We don't know whether it's well-defined or not, since we
haven't got a clue what the code is or does."

That is, the code is unknown, its behaviour is unknown.  Not undefined -
it may be well-defined - simply unknown.

Quote:
>>So how do we tell if UB is invoked?  Simple: we look at the code.

> The problem is that we don't have the code.

Exactly the point.  Without the code, we can't know it actually violates
any restriction which would render its behaviour undefined, therefore we
can't say UB is involved.

Quote:

>>Does the code use non-portable constructs?  We don't know.  [1] Does the
>>code use erroneous constructs?  We don't know. Does the code use
>>erroneous data?  We don't know. Does the code use intedterminately-value
>>objects?  We don't know. Does the code violate a "shall" or "shall not"
>>requirment, outside of a constraint?  We don't know. Does the standard
>>specifically mention clrscr, and slap a comment of "undefined behaviour"
>>on it?  No.

> The bottom line is that clrscr() has undefined behaviour because the
> standard doesn't contain any definition of behaviour for it.

The standard doesn't contain any definition of the behaviour of my
test_eof function, either.  

The standard _does_ however, contain a definition of the effects of the
code within the test_eof function.  That is, the standard says nothing
about any function called "test_eof", but the source code for the
function can be compared to the standard and thus determined to be
well-defined or not.

If the simple fact that the standard doesn't happen to describe a user
function is sufficient to conclude "UB", then it follows _all_ C code
must exist within main() or be rendered UB - you cannot write a function
or functions to simplify your code, because you would either violate
reserved function name spaces, or be using a name not specified by the
standard - in either case, invoking UB.

However, that's not the case.  The fact is you _can_ write functions,
call them anything you like modulo a few restrictions, and the standard
doesn't give a tinker's dam; what matters is what the code _inside_ the
function does - that code may invoke UB, or be well-defined.

Since we don't have the code for the clrscr function, we simply do not
know whether its behaviour is defined or not.

Quote:
>>That's six separate tests.  Of the six, five tell us we can't answer the
>>question, and the sixth says that if all the rest could be answered
>>"no", then the function wouldn't invoked undefined behaviour.

> In none of those tests can we constrain the behaviour of the function
> clrscr(). The only possible conclusion from each and every one of those
> tests is that the function has undefined behaviour.

Fine; please show us how the source code to clrscr violates the standard
in any way.

You can't.  So unless you're arguing that users are _prevented_ from
creating functions, without invoking UB, it follows that what we have is
simply _unknown_ behaviour.

Quote:
>>What we're left with, then, is five questions.  If the answer to any of
>>them is "yes", then the function invokes UB.

> No, if there is even the slightest possibility that the behaviour is
> unconstrained then the standard makes no requirement about what will
> happen and we have undefined behaviour.

You state the case too strongly; if there's a possibility that the
behaviour is unconstrained, then there is _a possibility_ that undefined
behaviour may be invoked.  Nobody is arguing otherwise.  The issue is
whether you can determine, without seeing the code, that UB *is* invoked.

So far, you haven't shown that this is the case.

Quote:
> Put it this way: is there any
> limitation on what clrscr() can do while still being part of a
> conforming implemtation? The answer is no. Total lack of limitation is
> called undefined behaviour

Again, either the source to clrscr does, or it does not, invoke UB,
thanks to an erroneous construct or a similar violation of the standard.
Without seeing the code, we don't know it contains an erroneous
construct, so all we can say is that its behaviour is _unkown_.
.

Quote:

>>So, _is_ the answer to any of the five questions "yes"?  No.  The answer
>>to all five is "We don't know."

> Which is enough.

To state our ignorance, yes.  However, making a conclusion based on
nothing but ignorance accomplishes nothing.

Quote:
>>As yet, despite the lengthy discussions, none of the supporters of the
>>proponent's position has in fact been able to answer any of those five
>>questions about the code, since they weren't provided with the code -
>>nor does it seem likely they will be able to answer those questions.

> The point is that an answer of "maybe" to those questions is enough to
> give undefined behaviour.

How so?  I don't see that in the standard.  That is, the standard
explicitly states that certain behaviours, such as use of an erroneous
construct, invoke UB.  If the best we can say is "we don't know", then we
cannot say that it _does_ contain an erroneous construct, so we cannot
say it invokes UB.

Quote:
> Only a categorical "no" can avoid it.

Only a categorical "yes" can affirm it.  A categorical "no" does avoid
it, true, but a statement of ignorance simply leaves the question
unanswered.

Quote:
> If you
> want to prove that the function does not invoke undefined behavour then
> you must prove that that the answer to each and every one of those
> questions is "no", and others as well.

I'm not attempting to prove no UB is involved; the question is how can
the original respondant *prove* - prove absolutely - that UB *is*
invoked, without seeing the code.

The answer is he can't.  Only by seeing the code can he determine that
erroneous constructs are used, or similar violations have occurred.
Since the code wasn't posted, he cannot make that determination.  Since
he cannot make that determination, he cannot say UB is involed.  Yet
that's exactly what he said; I simply called him on it - and so far,
nothing offered has suggested this analysis is wrong.

Quote:
>>[1] No, the use of the name "clrscr" does not appear to be a
>>non-portable construct.  That is, were the code for clrscr provided,
>>barring actual non-portable constructs _within_ the function, there's no
>>reason to suspect the code couldn't be compiled by any conforming
>>implementation; the fact the source to the function isn't included is no
>>more significant in this

...

read more »



Fri, 23 Jul 2004 20:40:01 GMT  
 clrscr and UB
[snips]

Quote:

>     f();
>     f(1);
>     f("hello");
>     f("world", 3L);

Thanks - couldn't remember if that were the case or not.

Quote:
>>So the question is, how to determine if it does, in fact, invoke UB?

> [snipped long version; here is my shorter version of the answer.]

> We must see the source for f(), and all the functions that f() calls.

Indeed.  My point.

Quote:
> If
> we cannot see that, we have only one other place to look: the C89
> standard.

Which, let's be clear here, defines, aside from implementation
details and the like, what source code can do and still have its
behaviour defined.

Quote:
> If the behavior of f() is not directly defined in the C
> standard, and the source code for f() is not ultimately visible, we have
> undefined behavior.

That's the crux of the issue.  I'm asking that you _explicitly_
delineate, from the standard, where well-formed code *is* UB, simply
because you, personally, don't happen to have a copy of it.

Quote:
> After applying this rule recursively, we will either have defined
> behavior (possibly including implementation-defined behavior within
> f()), or undefined behavior.  There are no shades of grey; there are
> only times when we do not yet know the answer (and therefore should be
> careful, lest it turn out to be "yes, there is undefined behavior").

And this is a case where we simply don't know the answer.  Why?  Because
we haven't seen the code, which may well be perfectly well-defined.

Quote:
>>In summation, from what has been discussed so far, there is absolutely
>>no possible way the respondant could have concluded that calling the
>>function in question did, indeed, invoke undefined behaviour.

> Indeed.  

Aha!  Finally, vindication. :)

Quote:
>>He may suspect it does, he may even have perfectly good reasons for
>>suspecting it does - but he cannot in actuality know it.

> Not in comp.lang.c, indeed.

Which was, in effect, the whole point.  I'm perfectly willing to
entertain the notion that the function may in fact violate, oh, say,
POSIX because POSIX has a clrscr function, but that one returns an array
of structs, and is therefore incompatible with the return type used.

However, as is often pointed out here, we do C.  Not POSIX, not *nix, not
Windows, C.  Given this, the poster _could not_ determine, in the context
of C, that the invocation of clrscr did, in fact, invoke UB; merely that
he suspected it might, or even that given the possibility that it might,
the cautious coder tends to assume it does, and in either case, posting
code using non-ISO functions for which code isn't provided is a good way
to get bad results.  But to conclude UB?  Nope, sorry.

Quote:
>  And of course, since people *are* people, you should not expect
> perfection.  Outside knowledge *will* leak in.  Those who know that most
> clrscr()s that people actually use do in fact use, at some point, some
> amount of undefined behavior, should probably be forgiven for not
> forgetting it here. :-)

Oh, absolutely.  I really didn't expect this to be as extensive a
harangue as it has become.  I rather expected it to be nothing more than
a trivial hand-slap, a sort of "careful there, you're jumping the gun
just a little" but instead it's turned into a three-ring circus involving
some of the most fabulously contrived non-answers I've every seen in the
newsgroup.

Oh well.  People will be people. :)



Fri, 23 Jul 2004 20:55:06 GMT  
 clrscr and UB

Quote:


> >> Anywhere the standard specifically states "undefined behaviour"

> > "Or by the omission of any explicit definition of behavior".

> The functionality of a piece of code may be perfectly well defined, but
> if you haven't got the code, you can't _know_ that it is well defined, so
> all you have is an unknown - not necessarily undefined behaviour.  To
> then say "must be UB" is an incorrect conclusion.

<sigh> _Calling_ unknown code does invoke UB, no matter whether that
code itself does so or not. It isn't clrscr() that invokes UB, it is the
code that calls clrscr() without having a non-UB definition of clrscr()
at hand that does so.

And since that disctinction is apparently not one you seem to grok, this
is the last I shall say on the subject. Furrfu.

Richard



Fri, 23 Jul 2004 21:52:58 GMT  
 clrscr and UB

Quote:



>> >> Anywhere the standard specifically states "undefined behaviour"

>> > "Or by the omission of any explicit definition of behavior".

>> The functionality of a piece of code may be perfectly well defined, but
>> if you haven't got the code, you can't _know_ that it is well defined,
>> so all you have is an unknown - not necessarily undefined behaviour. To
>> then say "must be UB" is an incorrect conclusion.

> <sigh> _Calling_ unknown code does invoke UB,

Really?  Fine; please post the relevant portion of the standard which
explicitly states that calling well-formed code, which you don't happen
to be able to see _as code_, invokes UB.

I'm betting you can't.



Sat, 24 Jul 2004 09:55:01 GMT  
 clrscr and UB
[snips]

Quote:

> If I were to write a function, call it clrscr, and very carefully check
> it to ensure it invoked UB

Should read "invoked no UB".


Sat, 24 Jul 2004 09:55:04 GMT  
 clrscr and UB

Quote:



>>> >> Anywhere the standard specifically states "undefined behaviour"

>>> > "Or by the omission of any explicit definition of behavior".

>>> The functionality of a piece of code may be perfectly well defined, but
>>> if you haven't got the code, you can't _know_ that it is well defined,
>>> so all you have is an unknown - not necessarily undefined behaviour. To
>>> then say "must be UB" is an incorrect conclusion.

>> <sigh> _Calling_ unknown code does invoke UB,

>Really?  Fine; please post the relevant portion of the standard which
>explicitly states that calling well-formed code, which you don't happen
>to be able to see _as code_, invokes UB.

If I am not able to see it as code, my translator is not able to see it
as code either.  The standard does not define the behaviour of such code,
therefore its behaviour is undefined.  The only functions that can be
called without supplying their definitions are the standard library
functions.

Quote:
>I'm betting you can't.

You've lost.

Dan
--
Dan Pop
DESY Zeuthen, RZ group



Sat, 24 Jul 2004 18:17:09 GMT  
 clrscr and UB

Quote:
> Really?  Fine; please post the relevant portion of the standard which
> explicitly states that calling well-formed code, which you don't happen
> to be able to see _as code_, invokes UB.

> I'm betting you can't.

Well, I need lunch money for today...
====================================================================
ISO/IEC 9899:1999 (E)

3.4.3

1 undefined behavior

  behavior, upon use of a nonportable or erroneous program construct
  or of erroneous data, for which this International Standard imposes
  no requirements

Without its definition (using only standard C) being part
of the program, 'clrscr()' is not a portable function.

You've lost the bet.  So how much was it for, anyway? ;-)
====================================================================

-Mike



Sun, 25 Jul 2004 05:13:49 GMT  
 clrscr and UB


Quote:
> [snips]


> >     f();
> >     f(1);
> >     f("hello");
> >     f("world", 3L);

> Thanks - couldn't remember if that were the case or not.

> >>So the question is, how to determine if it does, in fact, invoke UB?

> > [snipped long version; here is my shorter version of the answer.]

> > We must see the source for f(), and all the functions that f() calls.

> Indeed.  My point.

But this 'point' contradicts what you've been arguing.

Quote:
> > If
> > we cannot see that, we have only one other place to look: the C89
> > standard.

> Which, let's be clear here, defines, aside from implementation
> details and the like, what source code can do and still have its
> behaviour defined.

Right. *source code*.  A nonstandard function's definition
*must* be seen by the compiler in order for it to have
behavior defined by the language standard.

Quote:

> > If the behavior of f() is not directly defined in the C
> > standard, and the source code for f() is not ultimately visible, we have
> > undefined behavior.

> That's the crux of the issue.  I'm asking that you _explicitly_
> delineate, from the standard, where well-formed code *is* UB, simply
> because you, personally, don't happen to have a copy of it.

It's not a question of whether the programmer 'has a copy'.
It's the fact that it's not seen by the compiler.

Quote:

> > After applying this rule recursively, we will either have defined
> > behavior (possibly including implementation-defined behavior within
> > f()), or undefined behavior.  There are no shades of grey; there are
> > only times when we do not yet know the answer (and therefore should be
> > careful, lest it turn out to be "yes, there is undefined behavior").

> And this is a case where we simply don't know the answer.  Why?  Because
> we haven't seen the code, which may well be perfectly well-defined.

If the compiler can't see it, it cannot assess whether
it's 'well-defined.'  Thus its behavior is designated
as 'undefined.'

How many birds, if any, are currently sitting on the roof
of my house?  Being inside the house, I cannot know, so
from my perspective, this value is 'undefined'.

Quote:
> >>In summation, from what has been discussed so far, there is absolutely
> >>no possible way the respondant could have concluded that calling the
> >>function in question did, indeed, invoke undefined behaviour.

> > Indeed.

> Aha!  Finally, vindication. :)

I don't think so.  See 3.4.3/1

Quote:
> >>He may suspect it does, he may even have perfectly good reasons for
> >>suspecting it does - but he cannot in actuality know it.

> > Not in comp.lang.c, indeed.

> Which was, in effect, the whole point.  I'm perfectly willing to
> entertain the notion that the function may in fact violate, oh, say,
> POSIX because POSIX has a clrscr function, but that one returns an array
> of structs, and is therefore incompatible with the return type used.

> However, as is often pointed out here, we do C.  Not POSIX, not *nix, not
> Windows, C.  Given this, the poster _could not_ determine, in the context
> of C, that the invocation of clrscr did, in fact, invoke UB;

The fact that the compiler does not see the function's
definition *means* that it's behavior is 'undefined'
(by the language).

Quote:
> merely that
> he suspected it might, or even that given the possibility that it might,
> the cautious coder tends to assume it does, and in either case, posting
> code using non-ISO functions for which code isn't provided is a good way
> to get bad results.  But to conclude UB?  Nope, sorry.

Be as sorry as you like, but this is exactly how the
C language is defined.

Quote:

> >  And of course, since people *are* people, you should not expect
> > perfection.  Outside knowledge *will* leak in.  Those who know that most
> > clrscr()s that people actually use do in fact use, at some point, some
> > amount of undefined behavior, should probably be forgiven for not
> > forgetting it here. :-)

> Oh, absolutely.  I really didn't expect this to be as extensive a
> harangue as it has become.  I rather expected it to be nothing more than
> a trivial hand-slap, a sort of "careful there, you're jumping the gun
> just a little" but instead it's turned into a three-ring circus involving
> some of the most fabulously contrived non-answers I've every seen in the
> newsgroup.

So call the ISO standard 'contrived' if you want.  If nobody
had 'contrived' it, it would not exist, and the 'C world'
would be chaos.

Quote:

> Oh well.  People will be people. :)

Yup, and many insist upon clinging to their ignornace,
even in the face of facts. :-)

-Mike



Sun, 25 Jul 2004 05:23:23 GMT  
 clrscr and UB

Quote:
> If I am not able to see it as code, my translator is not able to see it
> as code either.  The standard does not define the behaviour of such code,
> therefore its behaviour is undefined.  The only functions that can be
> called without supplying their definitions are the standard library
> functions.

     I guess not (C99 5.1.1.1).  Here is a typical scenerio:

     - First translation unit (clrscr.c) contains clrscr().
     - Second translation unit (main.c) contains main().

     Step 1: clrscr.c is written in strict ISO C.  After a
             successful translation, the translated unit is
             preserved in a library and the source file removed.

     Step 2: one year later, main.c gets compiled and linked with
             the library.  This time, the translator is unable to
             see the source file clrscr.c.

     According to my reading, C explicitly allows third-party
libraries such as the one made in step 1 above (provided that
such libraries are translated on the same implementation).

     [Cross-posted to comp.std.c.]

Tak-Shing



Sun, 25 Jul 2004 06:00:09 GMT  
 clrscr and UB

Quote:

> > If I am not able to see it as code, my translator is not able to see it
> > as code either.  The standard does not define the behaviour of such
code,
> > therefore its behaviour is undefined.  The only functions that can be
> > called without supplying their definitions are the standard library
> > functions.

>      I guess not (C99 5.1.1.1).  Here is a typical scenerio:

>      - First translation unit (clrscr.c) contains clrscr().
>      - Second translation unit (main.c) contains main().

>      Step 1: clrscr.c is written in strict ISO C.  After a
>              successful translation, the translated unit is
>              preserved in a library and the source file removed.

>      Step 2: one year later, main.c gets compiled and linked with
>              the library.  This time, the translator is unable to
>              see the source file clrscr.c.

>      According to my reading, C explicitly allows third-party
> libraries such as the one made in step 1 above (provided that
> such libraries are translated on the same implementation).

They would not be disallowed under undefined behavior.  They simply would
not produce behavior defined by the standard.

Let's consider a different scenario.  Same machine, same compiler, but we
change compile switches.  This time, we use some implementation specific
switch that changes the calling convention to pass via registers.  Since
there is no formal name mangling requirement for the C language, we might
have exactly the same entry point names.  Is the behavior defined?

Let's consider a 3rd scenario.  Same machine, same compiler, but we upgrade.
We were using version x.yy but now we are on version z.qq.  Now, the old
compiler referenced symbols that were in the old libraries.  So this one
won't even link.

Let's consider a 4th scenario.  Same machine, same compiler.  The old code
assumes operating system Q, but we have changed our operating system to P.
There are calls to systems services that work differently.  There are direct
video writes which go into what is now protected memory.

It does not take much imagination to see where these portable libraries can
possibly break down.

One of the reasons why I think the open source movement has so much momentum
is that the portable library idea only "mostly" works.
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 "The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm



Sun, 25 Jul 2004 07:11:38 GMT  
 clrscr and UB

Quote:




>>> If I am not able to see it as code, my translator is not able to see it
>>> as code either.  The standard does not define the behaviour of such code,
>>> therefore its behaviour is undefined.  The only functions that can be
>>> called without supplying their definitions are the standard library
>>> functions.

>>      I guess not (C99 5.1.1.1).  Here is a typical scenerio:

>>      - First translation unit (clrscr.c) contains clrscr().
>>      - Second translation unit (main.c) contains main().

>>      Step 1: clrscr.c is written in strict ISO C.  After a
>>              successful translation, the translated unit is
>>              preserved in a library and the source file removed.

>>      Step 2: one year later, main.c gets compiled and linked with
>>              the library.  This time, the translator is unable to
>>              see the source file clrscr.c.

>>      According to my reading, C explicitly allows third-party
>> libraries such as the one made in step 1 above (provided that
>> such libraries are translated on the same implementation).

                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^

Quote:
> They would not be disallowed under undefined behavior.  They simply would
> not produce behavior defined by the standard.

     I would argue that the behaviour above is well-defined.

Quote:
> Let's consider a different scenario.  Same machine, same compiler, but we
> change compile switches.  [snip]

     Then it is not ``on the same implementation''.

Quote:
> Let's consider a 3rd scenario.  Same machine, same compiler, but we upgrade.
> We were using version x.yy but now we are on version z.qq.  [snip]

     Then it is not ``on the same implementation''.

Quote:
> Let's consider a 4th scenario.  Same machine, same compiler.  The old code
> assumes operating system Q, but we have changed our operating system to P.
> [snip]

     Then it is not ``on the same implementation''.

Quote:
> One of the reasons why I think the open source movement has so much momentum
> is that the portable library idea only "mostly" works.

     [OT] Well, but Java programmers would disagree...

Tak-Shing



Sun, 25 Jul 2004 08:28:37 GMT  
 clrscr and UB

Quote:




> >>> If I am not able to see it as code, my translator is not able to see
it
> >>> as code either.  The standard does not define the behaviour of such
code,
> >>> therefore its behaviour is undefined.  The only functions that can be
> >>> called without supplying their definitions are the standard library
> >>> functions.

> >>      I guess not (C99 5.1.1.1).  Here is a typical scenerio:

> >>      - First translation unit (clrscr.c) contains clrscr().
> >>      - Second translation unit (main.c) contains main().

> >>      Step 1: clrscr.c is written in strict ISO C.  After a
> >>              successful translation, the translated unit is
> >>              preserved in a library and the source file removed.

> >>      Step 2: one year later, main.c gets compiled and linked with
> >>              the library.  This time, the translator is unable to
> >>              see the source file clrscr.c.

> >>      According to my reading, C explicitly allows third-party
> >> libraries such as the one made in step 1 above (provided that
> >> such libraries are translated on the same implementation).
>                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
> > They would not be disallowed under undefined behavior.  They simply
would
> > not produce behavior defined by the standard.

>      I would argue that the behaviour above is well-defined.

> > Let's consider a different scenario.  Same machine, same compiler, but
we
> > change compile switches.  [snip]

>      Then it is not ``on the same implementation''.

> > Let's consider a 3rd scenario.  Same machine, same compiler, but we
upgrade.
> > We were using version x.yy but now we are on version z.qq.  [snip]

>      Then it is not ``on the same implementation''.

> > Let's consider a 4th scenario.  Same machine, same compiler.  The old
code
> > assumes operating system Q, but we have changed our operating system to
P.
> > [snip]

>      Then it is not ``on the same implementation''.

> > One of the reasons why I think the open source movement has so much
momentum
> > is that the portable library idea only "mostly" works.

>      [OT] Well, but Java programmers would disagree...

Your definition of the same implementation really shows exactly how
non-portable libraries are.

Do you know for certain the switches used to compile every library that you
use?  I am sure that the answer is no.  Are you absolutely certain that
every library that you use is made with exactly the same version of the
compiler?  Including the system libraries that you link in?

Imagine any library from the year 1980.  Will you link with it and use it?
I am very sure that it is not going to work, or if it does -- only by some
sort of magnificent accident.  The portability of a library file is
temporary at best.  Since the information on how it was built is not encoded
into the library itself, it becomes non-portable the moment it is created
(using your own definition).

No wonder (then) that the standards committee did not address the issues
associated with user libraries.  Quite frankly, I think that they are
completely insoluble.
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 "The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm



Sun, 25 Jul 2004 09:02:36 GMT  
 
 [ 25 post ]  Go to page: [1] [2]

 Relevant Pages 

1. You be (UB) or not you be

2. reverse string - UB

3. Scary UB

4. Converting unsigned char to signed char invokes UB?

5. String literals and UB

6. still UB?

7. UB, or a stupid mistake, or both?

8. Borland clrscr() function

9. clrscr(); in MSVC 5.0

10. Q: clrscr & gotoxy functions

11. how to clrscr() in VC++ v6.0

12. clrscr() in C ??? or similar

 

 
Powered by phpBB® Forum Software