Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

clrscr and UB

9 views
Skip to first unread message

Kelsey Bjarnason

unread,
Feb 3, 2002, 3:40:16 AM2/3/02
to
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.

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.

Chris Torek

unread,
Feb 3, 2002, 7:38:13 AM2/3/02
to
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()".

In article <pan.2002.02.03.00...@xxspamxx.telus.net>
Kelsey Bjarnason <kel...@xxspamxx.telus.net> writes:
>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:

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

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

>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)
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://63.193.109.35/torek/ (not always up) I report spam to abuse@.
"nos...@elf.eng.bsdi.com" *is* my address (one of many actually).

Lawrence Kirby

unread,
Feb 3, 2002, 6:33:06 AM2/3/02
to
On Sunday, in article
<pan.2002.02.03.00...@xxspamxx.telus.net>
kel...@xxspamxx.telus.net "Kelsey Bjarnason" wrote:

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

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

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

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

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

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

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

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

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

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

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

...

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

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

...

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

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------

Kelsey Bjarnason

unread,
Feb 4, 2002, 7:40:01 AM2/4/02
to
[snips]

On Sun, 03 Feb 2002 03:33:06 -0800, Lawrence Kirby wrote:

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

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

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

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

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

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


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


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


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

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


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

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

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

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

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

You're right, it is - because without it, you can't prove that it
violates anything, so you can't say UB is involed. I'm well aware of
this.

> With it you might be able to prove that the fucntion is well-defined
> according to the standard. Without it that is impossible.

However, a thing being impossible to prove *true* does not mean that it
is *false*. It may be possible to prove it false, but until it has been
proven false, its status is simply unknown.

Kelsey Bjarnason

unread,
Feb 4, 2002, 7:55:06 AM2/4/02
to
[snips]

On Sun, 03 Feb 2002 04:38:13 -0800, Chris Torek wrote:

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

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

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

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

>>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. :)

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

> 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. :)

Richard Bos

unread,
Feb 4, 2002, 8:52:58 AM2/4/02
to
Kelsey Bjarnason <kel...@xxspamxx.telus.net> wrote:

> On Sun, 03 Feb 2002 03:33:06 -0800, Lawrence Kirby wrote:
>
> >> 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

Kelsey Bjarnason

unread,
Feb 4, 2002, 8:55:01 PM2/4/02
to
On Mon, 04 Feb 2002 05:52:58 -0800, Richard Bos wrote:

> Kelsey Bjarnason <kel...@xxspamxx.telus.net> wrote:
>
>> On Sun, 03 Feb 2002 03:33:06 -0800, Lawrence Kirby wrote:
>>
>> >> 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.

Kelsey Bjarnason

unread,
Feb 4, 2002, 8:55:04 PM2/4/02
to
[snips]

On Mon, 04 Feb 2002 04:40:01 -0800, Kelsey Bjarnason wrote:

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

Dan Pop

unread,
Feb 5, 2002, 5:17:09 AM2/5/02
to

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'm betting you can't.

You've lost.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Mike Wahler

unread,
Feb 5, 2002, 4:13:49 PM2/5/02
to
Kelsey Bjarnason <kel...@xxspamxx.telus.net> wrote in message
news:pan.2002.02.04.17...@xxspamxx.telus.net...[snip]

> 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

Mike Wahler

unread,
Feb 5, 2002, 4:23:23 PM2/5/02
to

Kelsey Bjarnason <kel...@xxspamxx.telus.net> wrote in message
news:pan.2002.02.04.04...@xxspamxx.telus.net...

> [snips]
>
> On Sun, 03 Feb 2002 04:38:13 -0800, Chris Torek wrote:
>
> > 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.

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

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

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

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

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

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

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

>
> Oh well. People will be people. :)

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

-Mike

Tak-Shing Chan

unread,
Feb 5, 2002, 5:00:09 PM2/5/02
to
On 5 Feb 2002, Dan Pop wrote:

> 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

Dann Corbit

unread,
Feb 5, 2002, 6:11:38 PM2/5/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0202052112320.10675-100000@exeter...


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


Tak-Shing Chan

unread,
Feb 5, 2002, 7:28:37 PM2/5/02
to
On Tue, 5 Feb 2002, Dann Corbit wrote:

> "Tak-Shing Chan" <es...@city.ac.uk> wrote in message
> news:Pine.GSO.4.21.0202052112320.10675-100000@exeter...
>> On 5 Feb 2002, Dan Pop wrote:
>>
>>> 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...

Tak-Shing

Dann Corbit

unread,
Feb 5, 2002, 8:02:36 PM2/5/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0202060003520.13421-100000@exeter...


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.

William D. Tallman

unread,
Feb 5, 2002, 9:36:28 PM2/5/02
to
Kelsey Bjarnason wrote:

Yep. 1) "If a ``shall'' or ``shall not'' requirement that appears outside

of a constraint is violated, the behavior is undefined."

> Anywhere the standard specifically states "undefined behaviour"

Yep. 2) "Undefined behavior is otherwise indicated in this Standard by the
words ``undefined behavior'....."

Ummmm... where is 3)?

3) "...or by the omission of any explicit definition".

You have failed to specify the third of the three equally applicable
conditions:

"There is no difference in emphasis among these three; they all describe
``behavior that is undefined.''"

Note the use of the word "three" in the sentence above. That third
condition conclusively supports the assertion that clrscr() produces UB, as
nowhere does the standard mention clrscr(), creating an "omission of any
explicit definition" of clrscr().

Bill Tallman


James Kuyper Jr.

unread,
Feb 5, 2002, 10:59:34 PM2/5/02
to

The C standard only defines the behavior of an entire program, and only
defines it when the entire program is written in C. The "entire program"
must be considered as including the contents of all non-standard header
files that are #included (when a program #includes a standard header, if
it does so correctly, and is correct in all other regards, then it's the
implementation's responsibility to make sure your code works, regardless
of how it chooses to handle that #inclusion).

If clrscr() is written in some other language, the C standard can't say
anything to constrain the behavior of your program. If it is written in
C, the question of whether the program has defined behavior depends upon
what that source code is. It's quite an ordinary thing to write library
functions which have undefined behavior if called with the wrong
arguments, or called in the wrong context.
I doubt that any function named clrscr() could be written entirely in
strictly conforming code; the C standard doesn't describe screens, nor
how to clear them.

Tak-Shing Chan

unread,
Feb 6, 2002, 5:47:11 AM2/6/02
to
On Tue, 5 Feb 2002, Dann Corbit wrote:

> "Tak-Shing Chan" <es...@city.ac.uk> wrote in message

> news:Pine.GSO.4.21.0202060003520.13421-100000@exeter...


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

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

> [snip]


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

The information is not encoded but could be documented.
Anyway, libraries are non-portable by default--they can only be
used on the same implementation and nowhere else.

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

It is soluble but is outside the scope of C. If we could
extend the ELF format to include all relevant information...

Tak-Shing

Tak-Shing Chan

unread,
Feb 6, 2002, 5:55:41 AM2/6/02
to
On Wed, 6 Feb 2002, James Kuyper Jr. wrote:

> Tak-Shing Chan wrote:
>> 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.
>

> [snip]


>
> I doubt that any function named clrscr() could be written entirely in
> strictly conforming code; the C standard doesn't describe screens, nor
> how to clear them.

What about void clrscr(void) {}? It is strictly-conforming,
although it is not doing what you think it does.

Tak-Shing

Peter Nilsson

unread,
Feb 6, 2002, 6:26:38 AM2/6/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0202061010360.21042-100000@exeter...

Elements of Chemistry now!

Wasn't setting CHAR_BIT to Avogadro's Number bizarre enough!! ;)

--
Peter


James Kuyper Jr.

unread,
Feb 6, 2002, 7:54:01 AM2/6/02
to

Sorry - I phrased that badly. What I meant to says is that "Any
function named clrscr() is likely to be intended to do something that
cannot be written in strictly conforming code."

If all of the code for your program, including clrscr.c, is written in
C, and if it's all translated and executed by the same implementation of
C, and if that code as a whole constitutes a program with no undefined
behavior, then you won't have that kind of problem. It doesn't matter
whether the code for clrscr.c has since been removed, but it does
matter, very much, what that code actually said.

Whether or not a program that calls clrscr() is conforming can, in
principle, depend upon interactions between clrscr.c and the rest of
your program. The simplest example would be if clrscr.c defines any name
with external linkage in addition to clrscr() itself, and your program
chooses to define that same name, also with external linkage. There's
lots of far more subtle ways they can interact.

Jos A. Horsmeier

unread,
Feb 6, 2002, 10:09:20 AM2/6/02
to
"James Kuyper Jr." <kuy...@wizard.net> wrote in message
news:3C612845...@wizard.net...

> Tak-Shing Chan wrote:
> > On Wed, 6 Feb 2002, James Kuyper Jr. wrote:
> > > Tak-Shing Chan wrote:

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

> > > I doubt that any function named clrscr() could be written entirely in


> > > strictly conforming code; the C standard doesn't describe screens, nor
> > > how to clear them.

> > What about void clrscr(void) {}? It is strictly-conforming,
> > although it is not doing what you think it does.

> Sorry - I phrased that badly. What I meant to says is that "Any
> function named clrscr() is likely to be intended to do something that
> cannot be written in strictly conforming code."

This is totally silly of course, but the best I can come up with is:

void clrscr() {

unsigned int i;

for (i= 0; ++i; )
puts("\r\n");
}

but then again, the entire topic is silly.

kind regards,

Jos aka j...@gen.nl

Dan Pop

unread,
Feb 6, 2002, 12:11:09 PM2/6/02
to
In <Pine.GSO.4.21.0202052112320.10675-100000@exeter> Tak-Shing Chan <es...@city.ac
.uk> writes:

>On 5 Feb 2002, Dan Pop wrote:
>
>> 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.

At this point, what part of the standard defines the behaviour of the
program calling clrscr()?

The behaviour of the function became undefined the very moment its
source file was removed, because you could no longer use the standard
to figure out what the behaviour was (UB by lack of specification).

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

And provided that the source code is available, so that the standard can
provide a definition of behaviour for the code contained in the libraries.

Tak-Shing Chan

unread,
Feb 6, 2002, 3:50:44 PM2/6/02
to
On 6 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202052112320.10675-100000@exeter> Tak-Shing Chan <es...@city.ac
> .uk> writes:
>
>>On 5 Feb 2002, Dan Pop wrote:
>>
>>> 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.
>
> At this point, what part of the standard defines the behaviour of the
> program calling clrscr()?

Bad question. C99 5.1.1.1p1, cited above, explicitly define
the behaviour of separately translated translation units
preserved in libraries.

> The behaviour of the function became undefined the very moment its
> source file was removed, because you could no longer use the standard
> to figure out what the behaviour was (UB by lack of specification).

See above.

Tak-Shing

Dann Corbit

unread,
Feb 6, 2002, 4:59:53 PM2/6/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0202062039030.17577-100000@exeter...

> On 6 Feb 2002, Dan Pop wrote:
[snip]

> > At this point, what part of the standard defines the behaviour of the
> > program calling clrscr()?
>
> Bad question. C99 5.1.1.1p1, cited above, explicitly define
> the behaviour of separately translated translation units
> preserved in libraries.

Let's take a look:

"5.1.1.1 Program structure
1 A C program need not all be translated at the same time. The text of the
program is kept in units called source files, (or preprocessing files) in
this International Standard. A source file together with all the headers and
source files included via the preprocessing directive #include is known as a
preprocessing translation unit. After preprocessing, a preprocessing
translation unit is called a translation unit. Previously translated
translation units may be preserved individually or in libraries. The
separate translation units of a program communicate by (for example) calls
to functions whose identifiers have external linkage, manipulation of
objects whose identifiers have external linkage, or manipulation of data
files. Translation units may be separately translated and then later linked
to produce an executable program.
Forward references: linkages of identifiers (6.2.2), external definitions
(6.9), preprocessing directives (6.10)."

Not once in this passage do we find terms like "shall" or "shall not."

Under section 4, Conformance, we find this:
"1 In this International Standard, ''shall'' is to be interpreted as a
requirement on an implementation or on a program; conversely, ''shall not''
is to be interpreted as a prohibition.

2 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 International 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''."

It is my opinion that 5.1.1.1 places no restrictions on program behavior.
It is only showing what a possible behavior for some implementations might
be like. Further [IMO], definition of the behavior of object libraries
would be impossible to achieve, considering that there is no standard that
governs the behavior of object libraries.

Geoff Field

unread,
Feb 6, 2002, 8:01:13 PM2/6/02
to

"Jos A. Horsmeier" <j.a.ho...@wanadoo.nl> wrote in message
news:a3rgr2$2n4p$1...@scavenger.euro.net...

Ah! An infinite blocking function! Would this be how it's implemented on
the Deathstation 9000?

> but then again, the entire topic is silly.

As is the implementation above ;-)

Geoff

--
Geoff Field, Professional geek, amateur stage-levelling gauge.
Spamtraps: geoff...@hotmail.com, gcf...@bigmailbox.net, or
geoff...@great-atuin.co.uk; Real Email: gcfield at optusnet dot com dot
au
My band's web page: http://www.geocities.com/southernarea/


James Kuyper Jr.

unread,
Feb 6, 2002, 8:37:34 PM2/6/02
to
Geoff Field wrote:
>
> "Jos A. Horsmeier" <j.a.ho...@wanadoo.nl> wrote in message
> news:a3rgr2$2n4p$1...@scavenger.euro.net...
...

> > void clrscr() {
> >
> > unsigned int i;
> >
> > for (i= 0; ++i; )
> > puts("\r\n");
> > }
>
> Ah! An infinite blocking function! Would this be how it's implemented on

UINT_MAX is infinite?

Daniel Fox

unread,
Feb 6, 2002, 8:40:27 PM2/6/02
to

"Geoff Field" <geoff...@hotmail.com> wrote in message
news:10130436...@cswreg.cos.agilent.com...

> > void clrscr() {
> >
> > unsigned int i;
> >
> > for (i= 0; ++i; )
> > puts("\r\n");
> > }
>
> Ah! An infinite blocking function! Would this be how it's implemented on
> the Deathstation 9000?

Unsigned integers will wrap; this for loop will eventually terminate.

-Daniel

Geoff Field

unread,
Feb 6, 2002, 9:46:23 PM2/6/02
to
"Daniel Fox" <danielfox200...@hotmail.com> wrote in message
news:uTk88.102450$E4.39...@e3500-atl2.usenetserver.com...

Of course, you and James Kuyper, Jr are both correct. I missed the fact
that
the ++i was, in fact, in the part of the "for" construct where the
expression is
evaluated. If the loop had read "for (i = 0; ; ++i)" then we would have had
a
DS9000 implementation.

All I can say is "D'oh!"

Tak-Shing Chan

unread,
Feb 7, 2002, 12:29:39 PM2/7/02
to
On Wed, 6 Feb 2002, Dann Corbit wrote:

> It is my opinion that 5.1.1.1 places no restrictions on program behavior.

It does, if you read it in context. The restriction is the
rest of the Standard, which would apply to the said libraries.

> It is only showing what a possible behavior for some implementations might
> be like. Further [IMO], definition of the behavior of object libraries
> would be impossible to achieve, considering that there is no standard that
> governs the behavior of object libraries.

There is no such thing as ``possible behaviour for
implementations'' nor ``behaviour of object libraries''. In C,
programs have behaviours, implementations have not.

Tak-Shing

Dan Pop

unread,
Feb 7, 2002, 1:07:26 PM2/7/02
to
In <Pine.GSO.4.21.0202062039030.17577-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

>On 6 Feb 2002, Dan Pop wrote:
>
>> In <Pine.GSO.4.21.0202052112320.10675-100000@exeter> Tak-Shing Chan <es...@city.ac
>> .uk> writes:
>>
>>>On 5 Feb 2002, Dan Pop wrote:
>>>
>>>> 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.
>>
>> At this point, what part of the standard defines the behaviour of the
>> program calling clrscr()?
>
> Bad question. C99 5.1.1.1p1, cited above, explicitly define
>the behaviour of separately translated translation units
>preserved in libraries.

Only to the extent that their source code is available.

Imagine that you have compiled the "hello world" program and have
removed its source file. You no longer have a C program and, therefore,
the C standard can no longer define its behaviour.

This also applies to the case when only some parts of the source code
are no longer available.

Tak-Shing Chan

unread,
Feb 7, 2002, 1:37:32 PM2/7/02
to
On 7 Feb 2002, Dan Pop wrote:

> Only to the extent that their source code is available.

The source code is available during translation time, which
is all that we need. 5p1 says that translation environment and
execution environment are two separate environments. See also
translation phase 8.

Tak-Shing

Dan Pop

unread,
Feb 7, 2002, 1:12:09 PM2/7/02
to
In <Pine.GSO.4.21.0202071710190.22110-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

> There is no such thing as ``possible behaviour for
>implementations'' nor ``behaviour of object libraries''. In C,
>programs have behaviours, implementations have not.

But a C program consists exclusively of source code, regardless of how it
is translated. If some of its source code is missing, the C program is
no longer complete and its behaviour is no longer defined by the
standard.

William D. Tallman

unread,
Feb 8, 2002, 2:07:12 AM2/8/02
to
Tak-Shing Chan wrote:

I don't have a copy of the final standards. Did they change 4.2? If not,
then I'd really like to know where in C99 5.1.1.1p1 (or anywhere else, for
that matter) is 4.2 explicitly superceded? If the standard doesn't
explicitly define it, is it not then by definition UB?

I would think that if there were any exceptions to 4.2, they would be
identified as such, and I've found no such in the draft copy. Does such an
exemption or supercession exist in the final standards? If so, would
someone please cite it? It would seem that this is a profound issue.....

Confused newbie would appreciate a resolution here.... <grin>

Thanks,

Bill Tallman

Dan Pop

unread,
Feb 8, 2002, 4:32:25 AM2/8/02
to

I can't see anything relevant there.

This International Standard specifies the form and
establishes the interpretation of programs expressed in the
programming language C.

If you don't have the (full) C program, the standard cannot specify its
behaviour. And this means undefined behaviour. If you disagree, please
specify the behaviour of the following C program, according to the
C standard:

unsigned sleep(unsigned);

int main()
{
sleep(1);
return 0;
}

As far as I can see, there is nothing unspecified or implementation
defined in this program, so its behaviour MUST be either well defined
(in which case we have a strictly conforming program) or undefined.

Tak-Shing Chan

unread,
Feb 8, 2002, 6:05:08 AM2/8/02
to
On 7 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202071710190.22110-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>
>> There is no such thing as ``possible behaviour for
>>implementations'' nor ``behaviour of object libraries''. In C,
>>programs have behaviours, implementations have not.
>
> But a C program consists exclusively of source code, regardless of how it
> is translated. If some of its source code is missing, the C program is
> no longer complete and its behaviour is no longer defined by the
> standard.

The point that you have repeatedly missed, is that what
happens to the C program *physically* is outside of the scope of
the Standard (3p2). AFAIK, C programs can be written on a cake
and the translator can eat the cake as part of the translation
process.

Tak-Shing

Tak-Shing Chan

unread,
Feb 8, 2002, 6:13:16 AM2/8/02
to
On 8 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202071818400.24938-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>
>>On 7 Feb 2002, Dan Pop wrote:
>>
>>> Only to the extent that their source code is available.
>>
>> The source code is available during translation time, which
>>is all that we need. 5p1 says that translation environment and
>>execution environment are two separate environments. See also
>>translation phase 8.
>
> I can't see anything relevant there.
>
> This International Standard specifies the form and
> establishes the interpretation of programs expressed in the
> programming language C.
>
> If you don't have the (full) C program, the standard cannot specify its
> behaviour. And this means undefined behaviour. If you disagree, please
> specify the behaviour of the following C program, according to the
> C standard:

Can you do better than straw-man attacks? In my original
example, the complete C program (clrscr.c and main.c) is
available during translation. Your example is not.

Tak-Shing

Tak-Shing Chan

unread,
Feb 8, 2002, 6:49:02 AM2/8/02
to
On Fri, 8 Feb 2002, William D. Tallman wrote:

> Tak-Shing Chan wrote:
>> On 6 Feb 2002, Dan Pop wrote:
>>> At this point, what part of the standard defines the behaviour of the
>>> program calling clrscr()?
>>
>> Bad question. C99 5.1.1.1p1, cited above, explicitly define
>> the behaviour of separately translated translation units
>> preserved in libraries.
>
> I don't have a copy of the final standards. Did they change 4.2? If not,
> then I'd really like to know where in C99 5.1.1.1p1 (or anywhere else, for
> that matter) is 4.2 explicitly superceded? If the standard doesn't
> explicitly define it, is it not then by definition UB?

Sorry about the confusion. To be pedantic, I should say
``5.1.1.1p1 explicitly requires a conforming implementation to
allow separate translations, such that the behaviour of
separately-translated-units-linked-together-into-an-executable is
the same as the behaviour of the whole C program.'' Note that
the behaviour of the whole C program is defined by the rest of
the Standard.

The actual behaviour of the libraries themselves are outside
the scope of the Standard (1p2, mechanisms by which C programs
are transformed and invoked), so you cannot say ``undefined by
omission''.

Tak-Shing

Tak-Shing Chan

unread,
Feb 8, 2002, 6:52:25 AM2/8/02
to
On Fri, 8 Feb 2002, Tak-Shing Chan wrote:

> The point that you have repeatedly missed, is that what
> happens to the C program *physically* is outside of the scope of
> the Standard (3p2). AFAIK, C programs can be written on a cake
> and the translator can eat the cake as part of the translation
> process.

Typo: 1p2.

Tak-Shing

Dan Pop

unread,
Feb 8, 2002, 6:51:13 AM2/8/02
to

What makes you think so? sleep.c was compiled one year ago and removed
after that, just as clrscr.c in your original example.

So, please provide a proper answer to my question.

James Kuyper Jr.

unread,
Feb 8, 2002, 8:02:06 AM2/8/02
to
Dan Pop wrote:
>
> In <Pine.GSO.4.21.0202081105360.9523-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>
> >On 8 Feb 2002, Dan Pop wrote:
...

> > Can you do better than straw-man attacks? In my original
> >example, the complete C program (clrscr.c and main.c) is
> >available during translation. Your example is not.
>
> What makes you think so? sleep.c was compiled one year ago and removed
> after that, just as clrscr.c in your original example.

Therefore, every part of the entire C program was available, at the
times when it needed to be available. The fact that it wasn't all
available at the same time is irrelevant. If you believe otherwise,
please cite the text that says so.

Tak-Shing Chan

unread,
Feb 8, 2002, 8:08:34 AM2/8/02
to
On 8 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202081105360.9523-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>> Can you do better than straw-man attacks? In my original
>>example, the complete C program (clrscr.c and main.c) is
>>available during translation. Your example is not.
>
> What makes you think so? sleep.c was compiled one year ago and removed
> after that, just as clrscr.c in your original example.

In that case, the behaviour of the complete program is
defined by the rest of the Standard (5.1.1.1p1). Whether sleep.c
is *physically* present during the separate translation of main.c
is irrelevant to the complete program's behaviour and is outside
of the Standard's scope (1p2).

Tak-Shing

Dan Pop

unread,
Feb 8, 2002, 12:36:26 PM2/8/02
to

I have already done it, upthread. If you don't have access to the
sources NOW, the standard does not define the behaviour of your
program, because there is no way to tell what the parts without source
code are doing. Undefined behaviour by lack of specification.

Consider the case of a translated C program whose source code no
longer exists. What does the C standard guarantee about the behaviour
of this program?

Dan Pop

unread,
Feb 8, 2002, 12:40:17 PM2/8/02
to
In <Pine.GSO.4.21.0202081303100.15560-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

>On 8 Feb 2002, Dan Pop wrote:
>
>> In <Pine.GSO.4.21.0202081105360.9523-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>>> Can you do better than straw-man attacks? In my original
>>>example, the complete C program (clrscr.c and main.c) is
>>>available during translation. Your example is not.
>>
>> What makes you think so? sleep.c was compiled one year ago and removed
>> after that, just as clrscr.c in your original example.
>
> In that case, the behaviour of the complete program is
>defined by the rest of the Standard (5.1.1.1p1).

Please elaborate. I can't see anything in the standard defining the
behaviour of a piece of translated code whose source is no longer
available. As far as I can see, the standard deals exclusively in terms
of source code, no matter how it is translated. Therefore, in the
absence of source code, the standard can't define anything.

Dan Pop

unread,
Feb 8, 2002, 12:48:25 PM2/8/02
to
In <Pine.GSO.4.21.0202081116140.10757-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

> The actual behaviour of the libraries themselves are outside
>the scope of the Standard

Huh?

>(1p2, mechanisms by which C programs are transformed and invoked),

This is completely irrelevant to the discussion, nobody cared about
these mechanisms. You are confusing the behaviour of the code contained
in the libraries with the mechanisms by which the libraries have been
created.

>so you cannot say ``undefined by omission''.

Of course you can: no source code, no definition of behaviour.

Tak-Shing Chan

unread,
Feb 8, 2002, 1:44:07 PM2/8/02
to
On 8 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202081116140.10757-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>
>> The actual behaviour of the libraries themselves are outside
>>the scope of the Standard
>
> Huh?
>>(1p2, mechanisms by which C programs are transformed and invoked),
>
> This is completely irrelevant to the discussion, nobody cared about
> these mechanisms. You are confusing the behaviour of the code contained
> in the libraries with the mechanisms by which the libraries have been
> created.

These mechanisms are very relevant. Go and learn the
differences between a source file and a C program (5p1;
5.1.1.1p1) before you continue.

>>so you cannot say ``undefined by omission''.
>
> Of course you can: no source code, no definition of behaviour.

Nonsense. Go and learn the differences between a source
file and a C program (5p1; 5.1.1.1p1).

Tak-Shing

Tak-Shing Chan

unread,
Feb 8, 2002, 1:51:39 PM2/8/02
to
On 8 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202081303100.15560-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>> In that case, the behaviour of the complete program is
>>defined by the rest of the Standard (5.1.1.1p1).
>
> Please elaborate. I can't see anything in the standard defining the
> behaviour of a piece of translated code whose source is no longer
> available. As far as I can see, the standard deals exclusively in terms
> of source code, no matter how it is translated. Therefore, in the
> absence of source code, the standard can't define anything.

Source code is completely irrelevant. The Standard deals
exclusively in terms of a C program (an abstract entity), not in
terms of physical source files. The mechanism by which C
programs are transformed for use by a data-processing system is

Dann Corbit

unread,
Feb 8, 2002, 2:10:16 PM2/8/02
to
"Dan Pop" <Dan...@ifh.de> wrote in message
news:a41319$gud$1...@sunnews.cern.ch...


Which raises another question:

What about a C language system without a compiler -- it only includes a C
interpreter (OK, it's icky[tm] but I have seen C interpreters before)?

The standard library could be something completely internal to the compiler.
With the passage quoted about object libraries, is this implementation ruled
out of the standard as conforming since it produces neither objects nor
libraries?

Dann Corbit

unread,
Feb 8, 2002, 2:55:30 PM2/8/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0202081839030.1092-100000@exeter...

Where you see the words "source file" read "translation unit". I think it
goes without saying that a translation unit is a human-readable entity. A
collection of translation units makes up a C program. These translation
units may also reference C language headers which may or may not be "source
files" as well [they could be completely internal to the compiler in the
case of system headers].

If you are arguing that object files are portable C and always present well
defined behavior then I will say this:
If the standard says they are portable then the standard is wrong. Period.
Object files, even on a single system are not reliable after a short period
of time. So, even if the standard does (by some strange interpretation)
insist that they are portable and that their use results in clearly defined
behavior, they are not. Object files and object libraries are clearly
temporal entities. As they age, the probability of them working correctly
degenerates in an exponential manner. A 20 year old object file is almost
surely going to fail. A ten year old object file is very likely to fail. A
five year old object file will probably work. A ten minute old object file
is almost surely going to work. The same thing is not true of a conforming
C file. A conforming C file can be used at any time and does not degrade,
unless it uses features that become obsolete (at which time it is no longer
conforming).

I doubt very much if the ANSI or ISO C standard directly states that objects
and libraries are portable and their use results in defined behavior
anywhere. If it does, then the standard is "full of beans."

So, folks on news:comp.std.c -- I would like an interpretation. Does the C
Standard officially bless object files as conforming inputs to a C program?
Surely it must do so in the special case of the C compiler's library itself.
But what about the case of some arbitrary user object files or object
libraries obtained from 3rd parties?

Barry Margolin

unread,
Feb 8, 2002, 3:35:54 PM2/8/02
to
In article <a41a8...@enews2.newsguy.com>,

Dann Corbit <dco...@connx.com> wrote:
>If you are arguing that object files are portable C and always present well
>defined behavior then I will say this:
>If the standard says they are portable then the standard is wrong. Period.
>Object files, even on a single system are not reliable after a short period
>of time. So, even if the standard does (by some strange interpretation)

How short? The standard doesn't say, so by your logic they could be
unreliable 30 seconds after they're created, which is obviously ludicrous.

>insist that they are portable and that their use results in clearly defined
>behavior, they are not. Object files and object libraries are clearly
>temporal entities. As they age, the probability of them working correctly
>degenerates in an exponential manner. A 20 year old object file is almost
>surely going to fail. A ten year old object file is very likely to fail. A
>five year old object file will probably work. A ten minute old object file
>is almost surely going to work. The same thing is not true of a conforming
>C file. A conforming C file can be used at any time and does not degrade,
>unless it uses features that become obsolete (at which time it is no longer
>conforming).

Most implementors try hard to provide backward compatibility, so that
programs compiled in the past continue to work in future versions of the
OS, and old object files and libraries can be linked into new ones. I've
got an X application that I compiled almost 10 years ago when I was at a
previous employer. I compiled it under SunOS 4.x and it still works under
Solaris 2.6. This level of backward compatibility is not unusual, since
many sites don't have source code to the applications they run, and OS
vendors want them to upgrade.

None of this is required by the C standard of course. Essentially, the way
that object files and libraries are used is beyond its scope.

>I doubt very much if the ANSI or ISO C standard directly states that objects
>and libraries are portable and their use results in defined behavior
>anywhere. If it does, then the standard is "full of beans."

The object files themselves are not portable, but the concept of using them
is not, and the C standard makes explicit reference to this.

>So, folks on news:comp.std.c -- I would like an interpretation. Does the C
>Standard officially bless object files as conforming inputs to a C program?
>Surely it must do so in the special case of the C compiler's library itself.
>But what about the case of some arbitrary user object files or object
>libraries obtained from 3rd parties?

Object files and libraries are part of the mechanism that one uses to
execute a C program when using a compiler-based implementation (as opposed
to an interpreter). The details of invoking the compiler and executing the
result are implementation-dependent. The C standard blesses them as much
as it blesses the command line options you have to use to ensure that the
compiler is being run in ANSI-conformant mode.

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Dann Corbit

unread,
Feb 8, 2002, 3:55:08 PM2/8/02
to
"Barry Margolin" <bar...@genuity.net> wrote in message
news:JEW88.69$R16.120973@burlma1-snr2...

> In article <a41a8...@enews2.newsguy.com>,
> Dann Corbit <dco...@connx.com> wrote:
> >If you are arguing that object files are portable C and always present
well
> >defined behavior then I will say this:
> >If the standard says they are portable then the standard is wrong.
Period.
> >Object files, even on a single system are not reliable after a short
period
> >of time. So, even if the standard does (by some strange interpretation)
>
> How short? The standard doesn't say, so by your logic they could be
> unreliable 30 seconds after they're created, which is obviously ludicrous.

Nice straw man. Right below, I explain myself.

That is very, very unusal. Look at most other systems. E.g. OpenVMS (20
years ago would be VMS) used to run on VAX CISC chips and now runs on Alpha
RISC chps. 20 years ago, MS DOS was just born, and ran on 8 bit 8088 chips.
In other words, very little objects that are 20 years old will run. 10 year
old stuff has a decent chance of running (but not great)

> None of this is required by the C standard of course. Essentially, the
way
> that object files and libraries are used is beyond its scope.
>
> >I doubt very much if the ANSI or ISO C standard directly states that
objects
> >and libraries are portable and their use results in defined behavior
> >anywhere. If it does, then the standard is "full of beans."
>
> The object files themselves are not portable, but the concept of using
them
> is not, and the C standard makes explicit reference to this.

I assume that you mean ".. but the concept of using them is .." since
otherwise the above sentence runs contrary to your other discussion.

> >So, folks on news:comp.std.c -- I would like an interpretation. Does the
C
> >Standard officially bless object files as conforming inputs to a C
program?
> >Surely it must do so in the special case of the C compiler's library
itself.
> >But what about the case of some arbitrary user object files or object
> >libraries obtained from 3rd parties?
>
> Object files and libraries are part of the mechanism that one uses to
> execute a C program when using a compiler-based implementation (as opposed
> to an interpreter). The details of invoking the compiler and executing
the
> result are implementation-dependent. The C standard blesses them as much
> as it blesses the command line options you have to use to ensure that the
> compiler is being run in ANSI-conformant mode.

Does the standard say that the implementation must define the behavior as
you claim?

Where? Chapter and verse?

Barry Margolin

unread,
Feb 8, 2002, 6:43:01 PM2/8/02
to
In article <a41do...@enews2.newsguy.com>,

Dann Corbit <dco...@connx.com> wrote:
>That is very, very unusal. Look at most other systems. E.g. OpenVMS (20
>years ago would be VMS) used to run on VAX CISC chips and now runs on Alpha
>RISC chps. 20 years ago, MS DOS was just born, and ran on 8 bit 8088 chips.
>In other words, very little objects that are 20 years old will run. 10 year
>old stuff has a decent chance of running (but not great)

I think you'll find that many programs written for MS-DOS 20 years ago will
still run on Windows. The chip manufacturers also tend to be backward
compatible -- the Pentium instruction set is a superset of the 8086
instruction set.

I'm still running some programs on my Apple iBook that were written for
Macintosh 10 years ago. Apple went so far as to put 68000 emulation into
their Power Macintosh series of systems to ensure backward compatibility.

>Does the standard say that the implementation must define the behavior as
>you claim?
>
>Where? Chapter and verse?

The standard says that separate compilation is possible. What else could
that mean other than that you can link the resulting object files together?

James Kuyper Jr.

unread,
Feb 8, 2002, 7:47:43 PM2/8/02
to
Dan Pop wrote:
...

> available. As far as I can see, the standard deals exclusively in terms
> of source code, no matter how it is translated. ...

Yes, but source code is only needed during translation phase one, and is
no longer relevant for any given translation unit once that phase has
completed.

> ... Therefore, in the


> absence of source code, the standard can't define anything.

In the complete absence of source code, yes. However, the removal of the
source code after translation phase 1 has completed for each translation
unit, is something quite different from the complete absence of source
code.

James Kuyper Jr.

unread,
Feb 8, 2002, 8:12:54 PM2/8/02
to
Dan Pop wrote:

> In <3C63CD50...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:

...

>> times when it needed to be available. The fact that it wasn't all
>> available at the same time is irrelevant. If you believe otherwise,
>> please cite the text that says so.
>
>
> I have already done it, upthread. If you don't have access to the

I didn't notice any citation that appeared to be relevant to that claim.
Could you at least give the section number?

> sources NOW, the standard does not define the behaviour of your
> program, because there is no way to tell what the parts without source
> code are doing.

If an implementation supports seperate compilation, it must store the
translated translation unit in some fashion. Whatever medium it chooses
for that purpose (object files, possibly grouped together into a
library, are the only medium I've ever heard of) must contain all of the
information needed to link the program together and execute it; the
source code no longer needs to exist at that time.

In fact, it would be perfectly legal for an interactive C compiler to be
used, which parsed a translation unit as it is typed in, discarding any
parts it no longer needed, as soon as it no longer needed them, so that
the complete translation unit was never stored as such in memory or on
disk at any time. Such an implementation would be essentially unusuable
by human beings, but it would be legal.

>Undefined behaviour by lack of specification.

Yes, lack of specification is one of the listed ways in which the
behavior can be undefined. However, you have to be very careful about
invoking that option. For example, the standard says absolutely nothing
about hamburgers, or my brother, or eating. Does that mean that my
program has undefined behavior if translated or executed while my
brother is eating a hamburger? True; the standard does not define the
behavior of my brother, or of the hamburger, but the behavior of my
program remains just as well defined as it would have been if he hadn't
eaten the hamburger.

Sure, the behavior of the file system containing the source code is
undefined by the C standard, once the source code is erased. For
instance, the C standard says nothing about the fact that a directory
listing would no longer reflect the presence of that file. However, the
behavior of the translated code remains just as well defined as it was
when the source code was still in existence. It's the contents of the
source code file at the time that it was translated that matters. The
last phase in which those contents matter is phase 1, and the standard
requires that an implementation shall behave as if the phases were
handled seperately.

> Consider the case of a translated C program whose source code no
> longer exists. What does the C standard guarantee about the behaviour
> of this program?

It guarantees that the program operates exactly the same way it would if
the source code still existed; it does this by failing to specify that
the source code must still exist after having once been translated; or,
for that matter, at any point after translation phase 1.

James Kuyper Jr.

unread,
Feb 8, 2002, 8:40:34 PM2/8/02
to
Dann Corbit wrote:
>
> "Tak-Shing Chan" <es...@city.ac.uk> wrote in message
> news:Pine.GSO.4.21.0202081839030.1092-100000@exeter...
> > On 8 Feb 2002, Dan Pop wrote:
> >
> > > In <Pine.GSO.4.21.0202081116140.10757-100000@exeter> Tak-Shing Chan
> <es...@city.ac.uk> writes:
...

> > >>so you cannot say ``undefined by omission''.
> > >
> > > Of course you can: no source code, no definition of behaviour.
> >
> > Nonsense. Go and learn the differences between a source
> > file and a C program (5p1; 5.1.1.1p1).
>
> Where you see the words "source file" read "translation unit". I think it
> goes without saying that a translation unit is a human-readable entity. A

No, not only is that not obvious, it's also pretty unlikely.
Pre-processing translation units don't come into existence until
translation phases 1-3 have completed. Actual Translation units don't
come into existence until pre-processing is completed. By that point,
I'd expect the translation unit to be stored in whatever internal format
is used by the compiler, and it's rather unlikely that this format is
human-readable. The content of a translation unit is necessarily
equivalent to a single long string of basic source characters, and as
such it would be human readable. However, IMO it's pretty unlikely to be
stored in that form.

> collection of translation units makes up a C program. These translation
> units may also reference C language headers which may or may not be "source
> files" as well [they could be completely internal to the compiler in the
> case of system headers].

No, by the time that it constitutes a translation unit, all such
references have been resolved and removed.

> If you are arguing that object files are portable C and always present well
> defined behavior then I will say this:

Don't worry, no one's made any such suggestion, so you don't have to
argue against it. Now, it is the case that an object file created with a
given implementation of C will have well-defined behavior when linked by
the same implementation to other such object files, if the source code
that went into the creation of all those files defined a program with
well-defined behavior. That's true even if those files no longer exist,
and even if they were never all in existence at the same time. But
that's a very different claim from the straw man you're attacking.

> five year old object file will probably work. A ten minute old object file
> is almost surely going to work. The same thing is not true of a conforming
> C file. A conforming C file can be used at any time and does not degrade,
> unless it uses features that become obsolete (at which time it is no longer
> conforming).

Right - object files cease being useable when they are no longer
compatible with the current version of the implementation used to link
them together. Source code files cease being useable when they are no
longer compatible with the current version of the language standard.

> So, folks on news:comp.std.c -- I would like an interpretation. Does the C
> Standard officially bless object files as conforming inputs to a C program?

No - the standard says nothing about the use of object files as the
inputs to any program other than the linker, and the linker is not
necessarily a C program.

However, the standard does bless them as intermediate files to be used
by the implementation to store the encoded meaning of a source code file
after it's been translated, until such time as it is linked.

> Surely it must do so in the special case of the C compiler's library itself.
> But what about the case of some arbitrary user object files or object
> libraries obtained from 3rd parties?

Third party software is in the same category as user code, with respect
to the C standard. Whether or not a program that is created by linking
together one or more object files has defined behavior, depends upon the
source code that was used to create those object files (whether or not
that source code still exists at link time).

Dann Corbit

unread,
Feb 8, 2002, 8:29:20 PM2/8/02
to
"Barry Margolin" <bar...@genuity.net> wrote in message
news:9oZ88.74$R16.148240@burlma1-snr2...

> In article <a41do...@enews2.newsguy.com>,
> Dann Corbit <dco...@connx.com> wrote:
> >That is very, very unusal. Look at most other systems. E.g. OpenVMS (20
> >years ago would be VMS) used to run on VAX CISC chips and now runs on
Alpha
> >RISC chps. 20 years ago, MS DOS was just born, and ran on 8 bit 8088
chips.
> >In other words, very little objects that are 20 years old will run. 10
year
> >old stuff has a decent chance of running (but not great)
>
> I think you'll find that many programs written for MS-DOS 20 years ago
will
> still run on Windows. The chip manufacturers also tend to be backward
> compatible -- the Pentium instruction set is a superset of the 8086
> instruction set.

Can you link an object file emitted by Microsoft C or Lotus C or Manx C or
Aztec C with your current compiler? That's the question at hand -- not will
an old binary run. That's a completely different issue.

I suspect a lot fewer apps will run today than you think. A lot of them did
things like writing directly to the video frame buffer. That's a no-no
under NT.

> I'm still running some programs on my Apple iBook that were written for
> Macintosh 10 years ago. Apple went so far as to put 68000 emulation into
> their Power Macintosh series of systems to ensure backward compatibility.
>
> >Does the standard say that the implementation must define the behavior as
> >you claim?
> >
> >Where? Chapter and verse?
>
> The standard says that separate compilation is possible. What else could
> that mean other than that you can link the resulting object files
together?

I guess it means that a C interpreter is not allowed by the standard (one of
my other questions only in comp.lang.c).

The standard is wrong. Old objects won't link [except by accident]. Maybe
it says that they can. But it's wrong.

Things like void main() and i=i++ are not nearly so traumatic as attempting
to link a 20 year old object. I think the standard is full of crap, or it's
another "The emperor looks great in those new clothes!"

If the standard codifies something that is clearly impossible, then the
standard is broken.

William D. Tallman

unread,
Feb 8, 2002, 9:02:23 PM2/8/02
to
Tak-Shing Chan wrote:

> On Fri, 8 Feb 2002, William D. Tallman wrote:
>
>> Tak-Shing Chan wrote:
>>> On 6 Feb 2002, Dan Pop wrote:
>>>> At this point, what part of the standard defines the behaviour of the
>>>> program calling clrscr()?
>>>
>>> Bad question. C99 5.1.1.1p1, cited above, explicitly define
>>> the behaviour of separately translated translation units
>>> preserved in libraries.
>>
>> I don't have a copy of the final standards. Did they change 4.2? If
>> not, then I'd really like to know where in C99 5.1.1.1p1 (or anywhere
>> else, for
>> that matter) is 4.2 explicitly superceded? If the standard doesn't
>> explicitly define it, is it not then by definition UB?
>
> Sorry about the confusion. To be pedantic, I should say
> ``5.1.1.1p1 explicitly requires a conforming implementation to
> allow separate translations, such that the behaviour of
> separately-translated-units-linked-together-into-an-executable is
> the same as the behaviour of the whole C program.'' Note that
> the behaviour of the whole C program is defined by the rest of
> the Standard.

Okay......

> The actual behaviour of the libraries themselves are outside
> the scope of the Standard (1p2, mechanisms by which C programs
> are transformed and invoked), so you cannot say ``undefined by
> omission''.

?????

Well, I've just reviewed this entire thread, and it seems quite clear to me
that this current exchange has no significant bearing on the OP's
proposition that "clrscr() produces UB".

I think that the OP's assumption was the the function clrscr() was intended
to produce a clear terminal screen, or have I got that wrong? If so, I
extend my apologies for having added my confusion here. If not, however,
then I will again observe that there are holes in the arguments in this
thread large enough for an army to pass. I attempted to address those, but
got no response, and so will not do so again.

In any case, I conclude that this thread now concerns matters other than
the OP's statement, matters that I obviously don't understand. So I will
retire from the discussion.

Thanks for your response, though!

Bill Tallman

William D. Tallman

unread,
Feb 8, 2002, 9:28:28 PM2/8/02
to
Tak-Shing Chan wrote:

I don't get how any of that addresses whether or not "clrscr() produces UB".

But that's okay, because I think this entire thread is based on rather
egregiously invalid logic, and there is now nothing to which to argue. In
any case, thanks for responding.

Bill Tallman

William D. Tallman

unread,
Feb 8, 2002, 9:33:59 PM2/8/02
to
William D. Tallman wrote:


>> The actual behaviour of the libraries themselves are outside
>> the scope of the Standard (1p2, mechanisms by which C programs
>> are transformed and invoked), so you cannot say ``undefined by
>> omission''.
>
> I don't get how any of that addresses whether or not "clrscr() produces
> UB".
>
> But that's okay, because I think this entire thread is based on rather
> egregiously invalid logic, and there is now nothing to which to argue. In
> any case, thanks for responding.
>
> Bill Tallman

My goodness!!! Here's a poster who can't decide what he thinks!
Nevermind, both posts pretty much say the same thing anyway....

LOL!!!!!!!!!!!!!

Bill Tallman


James Kuyper Jr.

unread,
Feb 8, 2002, 11:20:17 PM2/8/02
to
Dann Corbit wrote:
>
> "Barry Margolin" <bar...@genuity.net> wrote in message
> news:9oZ88.74$R16.148240@burlma1-snr2...
...

> > The standard says that separate compilation is possible. What else could
> > that mean other than that you can link the resulting object files
> together?
...

> The standard is wrong. Old objects won't link [except by accident]. Maybe
> it says that they can. But it's wrong.

Don't worry - that's not what the standard says. It says absolutely
nothing about linking together objects compiled using different
implementations of C. Seperate compilation, and compilation by seperate
implementations of C, are two entirely different issues.

Dik T. Winter

unread,
Feb 9, 2002, 9:00:17 PM2/9/02
to
In article <3C6472B3...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
> > ... Therefore, in the
> > absence of source code, the standard can't define anything.
>
> In the complete absence of source code, yes. However, the removal of the
> source code after translation phase 1 has completed for each translation
> unit, is something quite different from the complete absence of source
> code.

But that is only the case if you stay on the same system with the same
compiler. So when the source code is absent the program is not portable,
regardless what the original source did. And if you try to port it the
result is really undefined behaviour.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Dik T. Winter

unread,
Feb 9, 2002, 9:05:18 PM2/9/02
to
In article <3C64784F...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
> However, the
> behavior of the translated code remains just as well defined as it was
> when the source code was still in existence. It's the contents of the
> source code file at the time that it was translated that matters.

This is false. The object code is tied to a specific compilation system,
so the behaviour is defined only within that compilation system, provided
of course that the original did not have undefined behaviour. So the
translated code is *not* just as well defined as the original source
code.

James Kuyper Jr.

unread,
Feb 9, 2002, 9:10:59 PM2/9/02
to
"Dik T. Winter" wrote:
>
> In article <3C6472B3...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
> > > ... Therefore, in the
> > > absence of source code, the standard can't define anything.
> >
> > In the complete absence of source code, yes. However, the removal of the
> > source code after translation phase 1 has completed for each translation
> > unit, is something quite different from the complete absence of source
> > code.
>
> But that is only the case if you stay on the same system with the same
> compiler. So when the source code is absent the program is not portable,
> regardless what the original source did. And if you try to port it the
> result is really undefined behaviour.

Agreed - as I've said repeatedly, the standard only defines what happens
if the entire program is translated and executed by a single
implementation of C. However, within that restriction, seperate
compilation does not, in itself, allow undefined behavior.

Dik T. Winter

unread,
Feb 9, 2002, 9:12:21 PM2/9/02
to
In article <3C647EFA...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
> Right - object files cease being useable when they are no longer
> compatible with the current version of the implementation used to link
> them together. Source code files cease being useable when they are no
> longer compatible with the current version of the language standard.

Object files are not useable right at the moment they are created when
moved to a different system. Source code has a longer lifetime.

> Third party software is in the same category as user code, with respect
> to the C standard. Whether or not a program that is created by linking
> together one or more object files has defined behavior, depends upon the
> source code that was used to create those object files (whether or not
> that source code still exists at link time).

Nope, it also depends on whether the same implementation is used. If
different implementations are used linking may or may not fail, if it
does not fail, execution may or may not fail. The standard tells us
nothing about that, so in my opinion this is undefined behaviour.

Joe Wright

unread,
Feb 9, 2002, 11:39:43 PM2/9/02
to
Any behavior for which 'this International Standard' imposes no
requirements is undefined behavior. What's so hard about that?
--
Joe Wright mailto:joeww...@earthlink.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

James Kuyper Jr.

unread,
Feb 10, 2002, 8:12:14 AM2/10/02
to
"Dik T. Winter" wrote:
>
> In article <3C64784F...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
> > However, the
> > behavior of the translated code remains just as well defined as it was
> > when the source code was still in existence. It's the contents of the
> > source code file at the time that it was translated that matters.
>
> This is false. The object code is tied to a specific compilation system,
> so the behaviour is defined only within that compilation system, provided
> of course that the original did not have undefined behaviour. So the
> translated code is *not* just as well defined as the original source
> code.

It is true that the object files can produce behavior that is not
defined by the C standard, if linked to files produced by a different
implementation of C, or by a linker that was incompatible with the
compiler that translated them (the behavior might, however, be defined
by a standard describing the linker). However, that is not something
that has anything to do with the presence or absence of the source code.
If the object files are used properly, the resulting program has defined
behavior, whether or not the source files were deleted between
compilation and linking. If the object files are used improperly, the
resulting program has undefined behavior, whether or not the source
files were deleted between compilation and linking. The erasure is
irrelevant to whether or not the behavior is defined.

The erasure does cause practical problems, in that you can't re-compile
the program when you have a change in compilers. However, that's a very
different issue from whether or not the behavior of a correctly linked
program is defined.

James Kuyper Jr.

unread,
Feb 10, 2002, 8:51:25 AM2/10/02
to
Joe Wright wrote:
>
> Any behavior for which 'this International Standard' imposes no
> requirements is undefined behavior. What's so hard about that?

Nothing. Except for the fact that you have to show that it applies.
Silence by the standard on a given issue is not enough to make the
behavior undefined. The key phrase is "no requirements". If no
requirements apply, then silence by the standard on a given issue means
that the behavior is undefined. However, if at least one requirement
does apply, silence on an issue means that the behavior is defined, in
the absence of any feature that has explicitly undefined behavior. For
instance, the standard does not define the behavior of an implementation
when someone drinks coffee while waiting for a program to compile.
However, that doesn't mean that the behavior of the code is undefined,
if you drink coffee. The standard imposes requirements on the
implementation, and the fact that it doesn't mention coffee does not
revoke those requirements.

For the specific case under discussion:
The standard requires that "A program that is correct in all other
aspects, operating on correct data, containing
unspecified behavior shall be a correct program and act in accordance
with 5.1.2.3.". (This is the same clause I'd cite in the coffee case).
The standard requires that "Implementations shall behave as if these
separate phases occur, ...", including phase 1, which is where the
source code file is read. Therefore, for a program which is correct in
all other aspects, whose source code was available when the standard
says it was needed, during translation phase 1, the standard does
imposes requirements on an implementation. Therefore, you can't use the
"no requirements" clause to use silence as an excuse for undefined
behavior. You need to find an explicit statement in the standard that
makes the behavior is undefined; there aren't any.

Now, it would be perfectly legal for an implementation to say that
translation phase 1 is not complete until just before the program starts
executing. However, any implementation which supports a compile phase
that is seperable from the link phase is implicitly proclaiming that
translation phases 1-7 are complete after compilation.

James Kuyper Jr.

unread,
Feb 10, 2002, 8:56:34 AM2/10/02
to
"Dik T. Winter" wrote:
>
> In article <3C647EFA...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
> > Right - object files cease being useable when they are no longer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> > compatible with the current version of the implementation used to link
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> > them together. Source code files cease being useable when they are no
> > longer compatible with the current version of the language standard.
>
> Object files are not useable right at the moment they are created when
> moved to a different system. Source code has a longer lifetime.

Exactly as I said; when moved to a different system, they may no longer
be compatible. Source code does have a longer lifetime. However, all I'm
saying is that erasing the source code does not make the behavior
undefined. Changing the system makes the behavior of the object files
undefined, and if the source code has been erased, you won't be able to
create new ones, but the erasure itself does not make the behavior
undefined.

> > Third party software is in the same category as user code, with respect
> > to the C standard. Whether or not a program that is created by linking
> > together one or more object files has defined behavior, depends upon the
> > source code that was used to create those object files (whether or not
> > that source code still exists at link time).
>
> Nope, it also depends on whether the same implementation is used. If

Why "Nope" when you're agreeing with me? That's precisely what I said in
the earlier paragraph.

Dan Pop

unread,
Feb 11, 2002, 4:05:53 AM2/11/02
to
In <Pine.GSO.4.21.0202081844340.1092-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

>On 8 Feb 2002, Dan Pop wrote:
>
>> In <Pine.GSO.4.21.0202081303100.15560-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>>> In that case, the behaviour of the complete program is
>>>defined by the rest of the Standard (5.1.1.1p1).
>>
>> Please elaborate. I can't see anything in the standard defining the
>> behaviour of a piece of translated code whose source is no longer
>> available. As far as I can see, the standard deals exclusively in terms
>> of source code, no matter how it is translated. Therefore, in the
>> absence of source code, the standard can't define anything.
>
> Source code is completely irrelevant. The Standard deals
>exclusively in terms of a C program (an abstract entity), not in
>terms of physical source files.

Where have I used the word "file" in my statements above?

But let's have a look at the standard:

5. Environment

[#1] An implementation translates C source files and
executes C programs in two data-processing-system
environments, which will be called the translation
environment and the execution environment in this
International Standard.
...
5.1.1.1 Program structure

[#1] A C program need not all be translated at the same
time. The text of the program is kept in units called
source files, (or preprocessing files) in this International
Standard. A source file together with all the headers and
source files included via the preprocessing directive
#include is known as a preprocessing translation unit.

So, next you're going to tell us that translation units are irrelevant
too :-)

>The mechanism by which C
>programs are transformed for use by a data-processing system is
>outside of the Standard's scope (1p2).

I don't remeber ever invoking "the mechanism by which C programs..." in
this thread, so I fail to see the relevance of this quote.

Dan Pop

unread,
Feb 11, 2002, 4:16:27 AM2/11/02
to
In <3C6472B3...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:

>Dan Pop wrote:
>...
>> available. As far as I can see, the standard deals exclusively in terms
>> of source code, no matter how it is translated. ...
>
>Yes, but source code is only needed during translation phase one, and is
>no longer relevant for any given translation unit once that phase has
>completed.

It is needed any time you need a definition of its behaviour, because the
C standard doesn't define anything in the absence of the source code.

>> ... Therefore, in the
>> absence of source code, the standard can't define anything.
>
>In the complete absence of source code, yes. However, the removal of the
>source code after translation phase 1 has completed for each translation
>unit, is something quite different from the complete absence of source
>code.

It's not different at all, if you need to know how the standard defines
the program's behaviour. If I give you an executable binary and tell you
that it was obtained by translating a strictly conforming C program, how
can you get the definition of its behaviour from the standard? If the
program doesn't behave the way I told you it will, how can you tell if
this is due to a bug in the program or to a non-conforming implementation?

Dan Pop

unread,
Feb 11, 2002, 4:30:43 AM2/11/02
to
In <3C64784F...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:

>Dan Pop wrote:
>
>> In <3C63CD50...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
>...
>
>>> times when it needed to be available. The fact that it wasn't all
>>> available at the same time is irrelevant. If you believe otherwise,
>>> please cite the text that says so.
>>
>> I have already done it, upthread. If you don't have access to the
>
>I didn't notice any citation that appeared to be relevant to that claim.
>Could you at least give the section number?

This International Standard specifies the form and
establishes the interpretation of programs expressed in the
programming language C.

>> sources NOW, the standard does not define the behaviour of your
>> program, because there is no way to tell what the parts without source
>> code are doing.
>
>If an implementation supports seperate compilation, it must store the
>translated translation unit in some fashion. Whatever medium it chooses
>for that purpose (object files, possibly grouped together into a
>library, are the only medium I've ever heard of) must contain all of the
>information needed to link the program together and execute it; the
>source code no longer needs to exist at that time.

I didn't argue that it needs to exist after translation phase 4. My point
was that if it doesn't exist, the standard can no longer define its
behaviour, because it only deals with source code constructs. And if the
standard doesn't define the program's behaviour, it's undefined, as far
as the standard is concerned.

>> Consider the case of a translated C program whose source code no
>> longer exists. What does the C standard guarantee about the behaviour
>> of this program?
>
>It guarantees that the program operates exactly the same way it would if
>the source code still existed;

But this is NOT a definition of behaviour. The behaviour is the same as
when the source code existed, but it is no longer defined by the standard.

>it does this by failing to specify that
>the source code must still exist after having once been translated; or,
>for that matter, at any point after translation phase 1.

Make that translation phase 4, because this is where #include directives
are processed.

Dan Pop

unread,
Feb 11, 2002, 4:57:12 AM2/11/02
to
In <Pine.GSO.4.21.0202081839030.1092-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

>On 8 Feb 2002, Dan Pop wrote:
>

>> In <Pine.GSO.4.21.0202081116140.10757-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>>

>>> The actual behaviour of the libraries themselves are outside
>>>the scope of the Standard
>>

>> Huh?
>>>(1p2, mechanisms by which C programs are transformed and invoked),
>>
>> This is completely irrelevant to the discussion, nobody cared about
>> these mechanisms. You are confusing the behaviour of the code contained
>> in the libraries with the mechanisms by which the libraries have been
>> created.
>

> These mechanisms are very relevant. Go and learn the


>differences between a source file and a C program (5p1;

>5.1.1.1p1) before you continue.

Please take your own advice and explain to the rest of us how you can have
a C program in the absence of its source files. And if you don't have a
C program, how can you get a definition of its behaviour from the
standard.

Besides, it is YOU, not me, who used the term "source file", in a futile
attempt to deviate the discussion in an irrelevant direction.

I was talking about "source code", which is a more abstract concept
(apparently too abstract for you, since you cannot disassociate it from
"source file"). Free clue: the source file is the container of the
source code (or "program text", as the standard itself calls it) that an
implementation needs during translation phases 1 to 4. The container
itself is irrelevant to the definition of the program's behaviour.

Dan Pop

unread,
Feb 11, 2002, 5:01:33 AM2/11/02
to
In <a417j...@enews1.newsguy.com> "Dann Corbit" <dco...@connx.com> writes:

>Which raises another question:
>
>What about a C language system without a compiler -- it only includes a C
>interpreter (OK, it's icky[tm] but I have seen C interpreters before)?
>
>The standard library could be something completely internal to the compiler.
>With the passage quoted about object libraries, is this implementation ruled
>out of the standard as conforming since it produces neither objects nor
>libraries?

The actual text of the standard is:

Previously translated translation units
may be preserved individually or in libraries.

Note the usage of the verb "may".

Tak-Shing Chan

unread,
Feb 11, 2002, 6:56:51 AM2/11/02
to
On 11 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202081844340.1092-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>> Source code is completely irrelevant. The Standard deals
>>exclusively in terms of a C program (an abstract entity), not in
>>terms of physical source files.

^^^^^^^^
> [Quote snipped, 5p1 and 5.1.1.1p1 w.r.t. ``source files'']


> So, next you're going to tell us that translation units are irrelevant
> too :-)

Nice straw-man. Which part of ``physical'' do you not
understand? Whether the physical files exist or not is none of
the Standard's business (1). C source files and C programs
(5.1.1.1) are abstract entities, not physical. Physical source
files belong to the scope of implementations. The Standard do
not know and do not care about ``rm -rf *'' during any
translation phases (1; 5.2.4.1). For a hypothetical mind-reading
implementation, physical source files do not even need to exist.

>>The mechanism by which C
>>programs are transformed for use by a data-processing system is
>>outside of the Standard's scope (1p2).
>
> I don't remeber ever invoking "the mechanism by which C programs..." in
> this thread, so I fail to see the relevance of this quote.

The mechanism could include undeletion of physical files.

The main argument in this thread amounts to appealing to
ignorance: ``if *I* have not seen its source code, then it is
undefined behaviour''. Counterexamples abound.

Tak-Shing

James Kuyper Jr.

unread,
Feb 11, 2002, 7:01:17 AM2/11/02
to
Dan Pop wrote:
>
> In <3C64784F...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
...

> This International Standard specifies the form and
> establishes the interpretation of programs expressed in the
> programming language C.

Which says nothing about ceasing to define their behavior just because
they've been erased. If they were erased before translation, then
there's an obvious problem with another section of the standard.
However, erasure after translation doesn't remove the fact that they
were "programs expressed in the programming language C", at the only
point in time when they needed to be.

...


> I didn't argue that it needs to exist after translation phase 4. My point

I'm sorry; you're right - it's phase 4, not phase 1, that matters.

> was that if it doesn't exist, the standard can no longer define its
> behaviour, because it only deals with source code constructs. And if the
> standard doesn't define the program's behaviour, it's undefined, as far
> as the standard is concerned.

If the code never existed, then I'd agree. But if the code ever existed,
it's behavior (if linked by the same implementation that it was compiled
by) continues to be defined by the contents of the code as it existed,
when it existed. It doesn't matter whether it still exists.

> >> Consider the case of a translated C program whose source code no
> >> longer exists. What does the C standard guarantee about the behaviour
> >> of this program?
> >
> >It guarantees that the program operates exactly the same way it would if
> >the source code still existed;
>
> But this is NOT a definition of behaviour. The behaviour is the same as
> when the source code existed, but it is no longer defined by the standard.

How does the behavior cease to be defined by the original source code,
just because the source code no longer exists? If the source code said a
= b+c, the standard continues to require that the translated source
code, when linked and executed, must add b to c, and put the result in
a. How does it matter whether the code has been erased?

Of course, if all copies of the code have been erased, there's no way to
verify whether or not the behavior is as defined by the standard.
However, the inability to verify that something is as defined is very
different from it being undefined.

James Kuyper Jr.

unread,
Feb 11, 2002, 7:16:44 AM2/11/02
to
Dan Pop wrote:
>
> In <3C6472B3...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
...

> It is needed any time you need a definition of its behaviour, because the
> C standard doesn't define anything in the absence of the source code.

True. And the only time that you need to define the behavior which the
program is supposed to have, is at the point where you tell the
implementation what the code is; i.e. during translation. Having defined
the behavior by providing the code at that point, it continues to be
defined even if the code is erased. It doesn't "need definition" any
longer, it already has one.

By the same logic, a soldier could cease following a verbal order, the
minute his commanding officer ceased repeating it out loud. After all,
what he's supposed to do is no longer defined, since the order is no
longer in existence. You can get executed for following that logic in
the army, and I'd advocate a similar attitude toward any compiler that
tried to get away with using the same logic with respect to my code and
the C standard.

> >> ... Therefore, in the
> >> absence of source code, the standard can't define anything.
> >
> >In the complete absence of source code, yes. However, the removal of the
> >source code after translation phase 1 has completed for each translation
> >unit, is something quite different from the complete absence of source
> >code.
>
> It's not different at all, if you need to know how the standard defines

Well, yes, if you need to know it, and no longer remember. That's not
the same as whether or not the behavior is defined.

> the program's behaviour. If I give you an executable binary and tell you
> that it was obtained by translating a strictly conforming C program, how
> can you get the definition of its behaviour from the standard? If the

I can't. That doesn't mean it isn't defined, it just means I can't tell
you what that defined behavior is. The defined behavior of that binary
is just another one of the enormous number of things in this world I
don't know, and can't find out. That doesn't mean that any of those
things don't exist. I don't know what color your hair is (or even if you
have any). Does that mean that your hair is colorless, or that you are
bald?

Dan Pop

unread,
Feb 11, 2002, 8:05:50 AM2/11/02
to
In <Pine.GSO.4.21.0202111030550.18403-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:

>On 11 Feb 2002, Dan Pop wrote:
>
>> In <Pine.GSO.4.21.0202081844340.1092-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>>> Source code is completely irrelevant. The Standard deals
>>>exclusively in terms of a C program (an abstract entity), not in
>>>terms of physical source files.
> ^^^^^^^^
>> [Quote snipped, 5p1 and 5.1.1.1p1 w.r.t. ``source files'']
>> So, next you're going to tell us that translation units are irrelevant
>> too :-)
>
> Nice straw-man. Which part of ``physical'' do you not
>understand? Whether the physical files exist or not is none of
>the Standard's business (1). C source files and C programs
>(5.1.1.1) are abstract entities, not physical. Physical source
>files belong to the scope of implementations.

And their removal belongs to the same scope. So, what is your point?

>The Standard do
>not know and do not care about ``rm -rf *'' during any
>translation phases (1; 5.2.4.1). For a hypothetical mind-reading
>implementation, physical source files do not even need to exist.

For the same implementation, forgetting the source code is the equivalent
of removing the physical source files. So, what exactly is your point?

Again, nobody but you talked about *physical* source files. You seem to
generate a strawman per post, lately.

>>>The mechanism by which C
>>>programs are transformed for use by a data-processing system is
>>>outside of the Standard's scope (1p2).
>>
>> I don't remeber ever invoking "the mechanism by which C programs..." in
>> this thread, so I fail to see the relevance of this quote.
>
> The mechanism could include undeletion of physical files.

So what? Both mechanism and physical files are irrelevant to the
discussion. The source code could be delivered together with the
library, on paper or microfiche.

> The main argument in this thread amounts to appealing to
>ignorance: ``if *I* have not seen its source code, then it is
>undefined behaviour''. Counterexamples abound.

If the source code is not available, the standard cannot specify its
behaviour.

Dan Pop

unread,
Feb 11, 2002, 8:09:03 AM2/11/02
to
In <3C67B39C...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:

>Dan Pop wrote:
>>
>> But this is NOT a definition of behaviour. The behaviour is the same as
>> when the source code existed, but it is no longer defined by the standard.
>
>How does the behavior cease to be defined by the original source code,
>just because the source code no longer exists?

How can a non-existing entity define anything at all?

Richard Bos

unread,
Feb 11, 2002, 8:19:42 AM2/11/02
to
"James Kuyper Jr." <kuy...@wizard.net> wrote:

> Dan Pop wrote:
> ...
> > available. As far as I can see, the standard deals exclusively in terms
> > of source code, no matter how it is translated. ...
>
> Yes, but source code is only needed during translation phase one, and is
> no longer relevant for any given translation unit once that phase has
> completed.
>

> > ... Therefore, in the
> > absence of source code, the standard can't define anything.
>
> In the complete absence of source code, yes. However, the removal of the
> source code after translation phase 1 has completed for each translation
> unit, is something quite different from the complete absence of source
> code.

In general, I think you're correct. Note, however, that this scenario
demands that we _know_ the original code was suitably conforming. The
linker has no memory; it cannot know whether the object file it is
linking does or does not invoke UB. It is the user who must make sure
that the code is indeed defined code.
In the case of a single user who compiles several translation units,
then deletes the source, then links them, that is easily guaranteed. If,
however, we have an object file, and we are told that it _could_ be
conforming, defined code, IMO linking it still defines UB, never mind
whether it originally was defined code or not. Why? Simply because we do
not _know_ that it was defined. We, the users, _don't_, and the
implementation _can't_.

In the post that sparked this thread, the latter was the case.
Someone(1) called clrscr(). Someone(2) else claimed that calling
clrscr() without providing a definition invokes UB. Someone(3) protested
that there could have been defined code for clrscr() elsewhere, and
therefore someone(2) cannot claim that calling it _does_ invoke UB, only
that it might.
IYAM, someone(2) is correct, as long as we have not seen defined code
for the function in question, or _know_, not guess, that it _is_, not
may be, well defined. BIANALL.
And note, this is IMO true only in this case, where we just do not know
anything about the called function. If we just compiled it and call it
while still knowing that it is defined, your argument holds.

Richard

Tak-Shing Chan

unread,
Feb 11, 2002, 9:11:21 AM2/11/02
to
On 11 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202081839030.1092-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>> These mechanisms are very relevant. Go and learn the
>>differences between a source file and a C program (5p1;
>>5.1.1.1p1) before you continue.
>
> Please take your own advice and explain to the rest of us how you can have
> a C program in the absence of its source files. And if you don't have a
> C program, how can you get a definition of its behaviour from the
> standard.

A comp.std.c expert (James Kuyper Jr.) has already answered
these two questions, repeatedly.

> Besides, it is YOU, not me, who used the term "source file", in a futile
> attempt to deviate the discussion in an irrelevant direction.

It is YOU who tried to deviate the discussion to irrelevant
directions. You have already lost your original argument:

(1) ``If I am not able to see it as code, my translator is
not able to see it as code either'' (6 Feb 2002).

(2) ``The standard does not define the behaviour of such
code, therefore its behaviour is undefined'' (6 Feb 2002).

Your first statement is trivially false (unless you are the
translator). Your second statement is irrelevant--if it is not
seen as code, where does your ``such code'' come from?

> I was talking about "source code", which is a more abstract concept
> (apparently too abstract for you, since you cannot disassociate it from
> "source file"). Free clue: the source file is the container of the
> source code (or "program text", as the standard itself calls it) that an
> implementation needs during translation phases 1 to 4. The container
> itself is irrelevant to the definition of the program's behaviour.

Source code, more abstract concept, apparently too abstract,
cannot disassociate it from "source file", clue, the container:
six non-standard terms in six lines. What is your point, if any?

Tak-Shing

Tak-Shing Chan

unread,
Feb 11, 2002, 9:12:57 AM2/11/02
to
On 11 Feb 2002, Dan Pop wrote:

> The actual text of the standard is:
>
> Previously translated translation units
> may be preserved individually or in libraries.
>
> Note the usage of the verb "may".

The actual text for strtok is:

``The separator string pointed to by s2 /may/ be different
from call to call.''

And your point is?

Tak-Shing

Tak-Shing Chan

unread,
Feb 11, 2002, 10:41:46 AM2/11/02
to
On 11 Feb 2002, Dan Pop wrote:

> In <Pine.GSO.4.21.0202111030550.18403-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
>> Nice straw-man. Which part of ``physical'' do you not
>>understand? Whether the physical files exist or not is none of
>>the Standard's business (1). C source files and C programs
>>(5.1.1.1) are abstract entities, not physical. Physical source
>>files belong to the scope of implementations.
>
> And their removal belongs to the same scope. So, what is your point?

So we are finally in agreement regarding the inapplicability
of C99 to physical files. The only disagreement here is about
the effects of removing C source files before TP8.

>>The Standard do
>>not know and do not care about ``rm -rf *'' during any
>>translation phases (1; 5.2.4.1). For a hypothetical mind-reading
>>implementation, physical source files do not even need to exist.
>
> For the same implementation, forgetting the source code is the equivalent
> of removing the physical source files. So, what exactly is your point?

As I have pointed out before (7 Feb 2002), C source files
are no longer needed at TP8 where the libraries are linked.

> Again, nobody but you talked about *physical* source files. You seem to
> generate a strawman per post, lately.

It is you, not me. You stated ``if I am not able to /see/


it as code, my translator is not able to see it as code either''

(6 Feb 2002). Your ability to see it implies the physical
manifestation of source files.

>> The mechanism could include undeletion of physical files.
>
> So what? Both mechanism and physical files are irrelevant to the
> discussion. The source code could be delivered together with the
> library, on paper or microfiche.

You have missed the main point: it does not have to be
delivered to *you*. It just need to be delivered to the
translator that produces the library.

>> The main argument in this thread amounts to appealing to
>>ignorance: ``if *I* have not seen its source code, then it is
>>undefined behaviour''. Counterexamples abound.
>
> If the source code is not available, the standard cannot specify its
> behaviour.

It has been said repeatedly (in the library example) that
the source code is available to the translator. The C Standard
applies to what the translator sees, not what you can see.

Tak-Shing

Tim Woodall

unread,
Feb 11, 2002, 10:50:06 AM2/11/02
to
On Mon, 11 Feb 2002 13:19:42 GMT,
Richard Bos <in...@hoekstra-uitgeverij.nl> wrote:
>
> In general, I think you're correct. Note, however, that this scenario
> demands that we _know_ the original code was suitably conforming. The
> linker has no memory; it cannot know whether the object file it is
> linking does or does not invoke UB. It is the user who must make sure
> that the code is indeed defined code.

Is this strictly true?

Were I to write a function:
int invoke_undefined_behaviour(int x) { return x++ + x; }
and compile it into a library.

I then delete the source and supply you with the library.
(I also tell you that the function returns 2*x+1)

If you call invoke_undefined_behaviour as part of an otherwise
well defined C program is the resultant program undefined?

Obviously we cannot say what it might do.

But if someone else reverse engineered the function and said
int invoke_undefined_behaviour(int x) { return x+x+1; } generates
identical assembly and an identical library and so provided you
with the "source" to the library. Does your code then become
defined a) If you do not recompile my library, b) if you do
recompile it with the well behaved code?

Perhaps followups should go to comp.lang.philosophy (if it
exists :-)

Tim.

--
God said, "div D = rho, div B = 0, curl E = - @B/@t, curl H = J + @D/@t,"
and there was light.

http://tjw.hn.org/ http://www.locofungus.btinternet.co.uk/

Dik T. Winter

unread,
Feb 11, 2002, 11:20:17 AM2/11/02
to
In article <Pine.GSO.4.21.0202111442310.1315-100000@exeter> Tak-Shing Chan <es...@city.ac.uk> writes:
> On 11 Feb 2002, Dan Pop wrote:
...

> > So what? Both mechanism and physical files are irrelevant to the
> > discussion. The source code could be delivered together with the
> > library, on paper or microfiche.
>
> You have missed the main point: it does not have to be
> delivered to *you*. It just need to be delivered to the
> translator that produces the library.

You have missed the main point: it could be delivered to the translator
together with the libary, on paper or microfiche.

Richard Bos

unread,
Feb 11, 2002, 11:49:59 AM2/11/02
to
t...@pauli.locofungus.org (Tim Woodall) wrote:

> On Mon, 11 Feb 2002 13:19:42 GMT,
> Richard Bos <in...@hoekstra-uitgeverij.nl> wrote:
> >
> > In general, I think you're correct. Note, however, that this scenario
> > demands that we _know_ the original code was suitably conforming. The
> > linker has no memory; it cannot know whether the object file it is
> > linking does or does not invoke UB. It is the user who must make sure
> > that the code is indeed defined code.
>
> Is this strictly true?
>
> Were I to write a function:
> int invoke_undefined_behaviour(int x) { return x++ + x; }
> and compile it into a library.
>
> I then delete the source and supply you with the library.
> (I also tell you that the function returns 2*x+1)
>
> If you call invoke_undefined_behaviour as part of an otherwise
> well defined C program is the resultant program undefined?

Yes, IMO.

In fact, I'd say it is even undefined if I call this function, and it is
not undefined but perfectly defined, _but_ I can no longer ascertain
that it is.

> Obviously we cannot say what it might do.

So, obviously, it is undefined.

Richard

Tak-Shing Chan

unread,
Feb 11, 2002, 12:39:36 PM2/11/02
to
On Mon, 11 Feb 2002, Dik T. Winter wrote:

>> You have missed the main point: it does not have to be
>> delivered to *you*. It just need to be delivered to the
>> translator that produces the library.
>
> You have missed the main point: it could be delivered to the translator
> together with the libary, on paper or microfiche.

I failed to see how this is relevant to my previous posts.
Specifically, I have repeatedly stated the physical format of the
actual source files in which the translator uses (be it paper or
microfiche) is outside of the scope of the Standard (1p2), and
thus your ``point'' is irrelevant to the current discussion.

Tak-Shing

Barry Margolin

unread,
Feb 11, 2002, 2:07:23 PM2/11/02
to
In article <a4825b$qpk$1...@sunnews.cern.ch>, Dan Pop <Dan...@ifh.de> wrote:
>It is needed any time you need a definition of its behaviour, because the
>C standard doesn't define anything in the absence of the source code.

Does it even contain a formal definition of source code? How do you know
if a particular file is "source code"?

The problem with your ultra-pedantic intepretation of the standard is that
it ignores reality. The standard is intended to be read by people with
common sense and who are familiar with the context of computer systems and
programming languages. It doesn't go into detail about the general
operation of these systems, because a) that would be beyond the scope of
the standard, and b) they can vary quite a bit between implementations
(just consider the differences between compilers and interpreters).

It's up to the user to understand how to apply the notions that the
standard refers to, such as separate compilation and libraries, to the
particular computing system they're using. For instance, if Solaris 2.6 is
upward compatible with Solaris 2.5, you know that you should be able to
take a program compiled for 2.5 and run it under 2.6 with the same expected
results. This is not a detail that can reasonably be spelled out in the C
standard.

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Barry Margolin

unread,
Feb 11, 2002, 2:15:40 PM2/11/02
to
In article <a48303$r1q$1...@sunnews.cern.ch>, Dan Pop <Dan...@ifh.de> wrote:
>I didn't argue that it needs to exist after translation phase 4. My point
>was that if it doesn't exist, the standard can no longer define its
>behaviour, because it only deals with source code constructs.

But can't we refer to what the source file used to contain? Isn't it
possible to reason about things that don't exist any more?

Dann Corbit

unread,
Feb 11, 2002, 1:57:25 PM2/11/02
to
"Tak-Shing Chan" <es...@city.ac.uk> wrote in message
news:Pine.GSO.4.21.0202111733510.9095-100000@exeter...

The point isn't "What format exactly are these sources in?"

It is (rather) "Are the sources necessary?"
--
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


Kelsey Bjarnason

unread,
Feb 11, 2002, 2:25:02 PM2/11/02
to
[snips]

Sorry, been busy lately...

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

Please show the nonportable or erroneous program construct defined within
the body of clrscr, or the erroneous data being used.

You can't, since you don't have the code. The code that you _do_ have
contains no erroneous or nonportable constructs (that is, if you were
provided with the body of the clrscr function, presuming it to be
conforming code, you could subsequently compile the whole program
_without_ having to moify the code you already have, since it does not
contain erroneous or non-portable constructs).

So again, see the question I asked.

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

Wrong; clrscr may be a perfectly portable function. What you mean is
that _you_ can't move it to another compiler _unless_ you get the code
for it. That doesn't make it non-portable, it simply means you need to
get the code in order to "port" it.

The same would be true if you had a function library (say, math
functions) which you typically linked in, but which you _did_ have source
for - on the original disks, you just nevre bothered installing the
source.

The code may be perfectly portable. The fact that it doesn't happen to
be sitting on the same drive as your sources is irrlevant - should you
wish to "port" it, you'd just go get the code.

Tak-Shing Chan

unread,
Feb 11, 2002, 2:51:16 PM2/11/02
to
On Mon, 11 Feb 2002, Dann Corbit wrote:

> The point isn't "What format exactly are these sources in?"
>
> It is (rather) "Are the sources necessary?"

Definitely not in TP8. In fact, Dan Pop goes even further
to assert that source files are not needed after TP4 (``make that
translation phase 4''). So he seems to be contradicting himself.

Tak-Shing

Thomas Stegen

unread,
Feb 11, 2002, 2:59:51 PM2/11/02
to
"Dan Pop" <Dan...@ifh.de> wrote in message
news:a48fpf$5r9$1...@sunnews.cern.ch...

> In <3C67B39C...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net>
writes:
>
> >Dan Pop wrote:
> >>
> >> But this is NOT a definition of behaviour. The behaviour is the same
as
> >> when the source code existed, but it is no longer defined by the
standard.
> >
> >How does the behavior cease to be defined by the original source code,
> >just because the source code no longer exists?
>
> How can a non-existing entity define anything at all?
>

I wouldn't use a computer with so many programs
invoking UB. Many of the programs I am using was
probably written in C, I haven't seen the source code
and the programmers probably hadn't seen a lot of the
code for the libraries, and who knows some of that
source code might not exist any more.

Also how can you be so sure that a compiled program
really was compiled from the source it was supplied
with? You can't. Hence, by your argument any program
which you didn't compile yourself invokes UB.


--
Thomas.

Approaching singularity.


Dann Corbit

unread,
Feb 11, 2002, 3:30:58 PM2/11/02
to
"Thomas Stegen" <tho_s...@hotmail.com> wrote in message
news:a49830$nsp$1...@dennis.cc.strath.ac.uk...


I think the argument would be (rather) that any program which uses objects
or libraries containing functions without source code and which are not
supplied by the implementation's standard library invokes undefined
behavior.

I think that is a true statement.

If the behavior is defined, what must it be? What does clrscr() or utime()
do?

Behavior can be defined by something outside of the standard.
Implementations can add extensions or we can use POSIX stuff or GKS or PHIGS
and know how these things are going to behave outside of the C standard
because they are documented elsewhere.

As far as the C language is concerned, I think the behavior is undefined.

Suppose that I link against a Winsock library and it turns out to be OS/2
instead of Win32. Demons come flying out of my nose, even though I have
used the API's correctly.

Here is what we can know:
1. If the objects and libraries in use were composed completely from
ANSI/ISO compliant code (both at the time of compiling and also the code
would still be or have been compliant at the time of linking -- standards
change)
2. If the objects are compatible with the current compiler[*]
3. If the objects are compatible with the current operating system[*]
4. If the compiler is operating in ANSI/ISO mode both at the time earlier
compile and now
5. If the compiler itself is not changed and/or is compatible with the
version that compiled the objects
6. If the linker and object librarian system are also compatible with all
objects

{If any of the above requirements can be left out, which is it? I imagine
that there are several more as well, that did not occur to me.} Then the
behavior can be defined. However, lacking source code, how will we verify
it? It now depends upon the memory of the programmer. Sounds like a pretty
loose definition of compliant and defined behavior to me. One thing for
sure -- lacking source code it is clearly impossible to prove compliance.
Unless we have somehow figured out whether or not the Turing machine will
halt.

[*] Whatever that means

Barry Margolin

unread,
Feb 11, 2002, 5:31:21 PM2/11/02
to
In article <a499e...@enews4.newsguy.com>,

Dann Corbit <dco...@connx.com> wrote:
>{If any of the above requirements can be left out, which is it? I imagine
>that there are several more as well, that did not occur to me.} Then the
>behavior can be defined. However, lacking source code, how will we verify
>it?

Why do you need to verify it? Some things have to be accepted as given
unless you have evidence otherwise.

If the vendor lies to you about the nature of the library, then things
won't work as expected. This is because you were misinformed, not because
your program doesn't follow the standard.

Suppose you use the fopen() function, but the implementation has a bug in
the code for this. Your program will still misbehave, even though it's
totally conforming.

Either way, the vendor misinformed you about what their library: in the
first case it was about whether the library is compatible with your
implementation, in the second it was about whether they correctly implement
the ANSI/ISO standard library.

Dann Corbit

unread,
Feb 11, 2002, 6:36:48 PM2/11/02
to
"Barry Margolin" <bar...@genuity.net> wrote in message
news:ZCX98.27$g01.152539@burlma1-snr2...

> In article <a499e...@enews4.newsguy.com>,
> Dann Corbit <dco...@connx.com> wrote:
> >{If any of the above requirements can be left out, which is it? I
imagine
> >that there are several more as well, that did not occur to me.} Then the
> >behavior can be defined. However, lacking source code, how will we
verify
> >it?

Accept what? I have a object module with a function called clrscr() in it.
Maybe it's from a vendor. Maybe I compiled it myself. Maybe I downloaded
it from Simtel. Maybe I can't even remember. The question is: "What does
it do?" The answer is...
Not defined by the C language unless I have the source code.

> Why do you need to verify it? Some things have to be accepted as given
> unless you have evidence otherwise.

Unless it is documented, it is silly to accept it. If it is documented,
then:
1. If it is a vendor product, then the vendor must accept some risk that it
will work as documented
2. If it is not a vendor product, then the tool user incurs all risk.

In either case, the C language standard says nothing about what it does or
might do.

> If the vendor lies to you about the nature of the library, then things
> won't work as expected. This is because you were misinformed, not because
> your program doesn't follow the standard.

The standard I am relying on (in this case) is the extension offered by the
vendor. It is not something endorsed by the C language. Rather, it is
something that I hope will work, and if it fails, I will have to plead with
the vendor to fix it or take them to court or whatever.

> Suppose you use the fopen() function, but the implementation has a bug in
> the code for this. Your program will still misbehave, even though it's
> totally conforming.

If they claim to have an ANSI compiler then I can use that in a court of law
to defend myself. If I am using the fraboozle() function, then I am at
considerably more risk (IMO).

> Either way, the vendor misinformed you about what their library: in the
> first case it was about whether the library is compatible with your
> implementation, in the second it was about whether they correctly
implement
> the ANSI/ISO standard library.

And one is covered by the ANSI/ISO standard and the other is not.
Personally, I think it is absurd to assume that systems outside of the
standard are conforming. From the point that we start using vendor
extensions on forward, we are operating on trust.

Did the vendor use assembly language extensions? Did the vendor have i=i++
in his code? There is absolutely no way for me to know. I don't see how
anyone can say that usage of non-standard libraries or objects results in
defined behavior. "Defined by what?" Certainly not by the C Standard. If
(by some miracle) every construct in the library is pure and 100% correct
ANSI C, I will still have no way to verify it.

That does not mean that programs using these sort of things cannot create
correct results. But I believe that we no longer have the ANSI standard as
a protection once we do (at least for any parts of a system that directly
rely upon things not covered by the standard).

Sometimes we will have to use this sort of extension (or inline assembly or
whatever...)
Sometimes these extensions are a very good idea. But I think it is an
illusion to imagine that the behavior of programs that rely upon them are
standardized or somehow compliant and producing ANSI/ISO defined behaviors.
The behaviors we receive are (rather) vendor defined. And so using them is
a function of how much we trust that particular vendor.

James Kuyper Jr.

unread,
Feb 11, 2002, 8:11:43 PM2/11/02
to
Dan Pop wrote:
>
> In <3C67B39C...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net> writes:
...

> >How does the behavior cease to be defined by the original source code,
> >just because the source code no longer exists?
>
> How can a non-existing entity define anything at all?

By having been in existence at the time it needed to exist, in order to
define the behavior.

James Kuyper Jr.

unread,
Feb 11, 2002, 8:30:00 PM2/11/02
to
Dann Corbit wrote:
>
> "Thomas Stegen" <tho_s...@hotmail.com> wrote in message
> news:a49830$nsp$1...@dennis.cc.strath.ac.uk...
> > "Dan Pop" <Dan...@ifh.de> wrote in message
> > news:a48fpf$5r9$1...@sunnews.cern.ch...
> > > In <3C67B39C...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net>
> > writes:
...

> If the behavior is defined, what must it be? What does clrscr() or utime()
> do?

Precisely what it's source code said it should do. Whether that source
code still exists determines whether or not you can determine whether
the behavior of that code is defined, but that doesn't change whether or
not the code's behavior is defined.

...


> Suppose that I link against a Winsock library and it turns out to be OS/2
> instead of Win32. Demons come flying out of my nose, even though I have
> used the API's correctly.

Yes - because the compiler that was used to compile that code, and the
linker that was used to link it, do not together constitute a conforming
implementation of C. That is completely independent of whether or not
the source code still exists.

> Here is what we can know:

[Long list of requirements for successful seperate compilation]


> {If any of the above requirements can be left out, which is it? I imagine

None, but they all boil down to one requirement: the code must be
compiled and linked by a compiler and linker that together constitute a
conforming implementation of C (taking into the consideration the
compiler/linker options that were specified). Every single item you
listed will (usually, but not necessarily) create a situation where he
combination is not a conforming implmentation.

...


> that there are several more as well, that did not occur to me.} Then the
> behavior can be defined. However, lacking source code, how will we verify
> it?

Code that has undefined behavior is different from code that can't be
proven to have defined behavior. It's precisely the same distinction as
the one between people who are guilty of murder, and people who can't be
proven innocent of murder. Ideally, the first group is a subset of the
second, but it is not the same as the second group (in either case).

> loose definition of compliant and defined behavior to me. One thing for
> sure -- lacking source code it is clearly impossible to prove compliance.

True. That doesn't mean the code isn't compliant, merely that you can't
find out whether it's compliant.

James Kuyper Jr.

unread,
Feb 11, 2002, 8:51:13 PM2/11/02
to
Richard Bos wrote:
>
> "James Kuyper Jr." <kuy...@wizard.net> wrote:
...

> > In the complete absence of source code, yes. However, the removal of the
> > source code after translation phase 1 has completed for each translation
> > unit, is something quite different from the complete absence of source
> > code.
>
> In general, I think you're correct. Note, however, that this scenario
> demands that we _know_ the original code was suitably conforming. The
> linker has no memory; it cannot know whether the object file it is
> linking does or does not invoke UB. It is the user who must make sure
> that the code is indeed defined code.

You're missing the point of UB. The linker isn't responsible for
checking for UB. It's only responsible for making sure that it produces
the defined behavior, when the behavior is defined. A linker has all the
memory it needs, to achieve this - that memory is called "object files".
The linker doesn't need to know what that behavior is; it's just
responsible for following the instructions placed in those files by the
compiler. It's up to the compiler to put into those files whatever
information the linker needs to produce the behavior defined by the
standard. And if it did do so, the program will produce the defined
behavior, even if the source code that told the compiler what that
behavior should be, has since disappeared.

> In the case of a single user who compiles several translation units,
> then deletes the source, then links them, that is easily guaranteed. If,
> however, we have an object file, and we are told that it _could_ be
> conforming, defined code, IMO linking it still defines UB, never mind
> whether it originally was defined code or not. Why? Simply because we do
> not _know_ that it was defined. We, the users, _don't_, and the
> implementation _can't_.

Just because you don't know what the defined behavior is, doesn't mean
that the behavior isn't defined. Just because you don't know what color
my car is, doesn't mean that my car is colorless.

Dann Corbit

unread,
Feb 11, 2002, 8:32:16 PM2/11/02
to
"James Kuyper Jr." <kuy...@wizard.net> wrote in message
news:3C686CBD...@wizard.net...

This is starting to sound like:
"If a tree falls in a forest with no ear to hear it..."

If I email an object module to you, and claim that it is conformant and
exhibits always defined behavior, and then you link a program with it, is
the behavior of the program defined?

Is the memory of the programmer "This thing has no undefined behavior that I
recall" enough to make the behavior defined?

Must defined behavior be verifiable, or is a memory enough to make it so?
If a memory that a program was well defined is enough, do we even need to
examine source code to determine correctness? Maybe we should all delete
our source code after the apps ship.
;-)

James Kuyper Jr.

unread,
Feb 11, 2002, 9:39:34 PM2/11/02
to
Dann Corbit wrote:
>
> "James Kuyper Jr." <kuy...@wizard.net> wrote in message
> news:3C686CBD...@wizard.net...
> > Dan Pop wrote:
> > >
> > > In <3C67B39C...@wizard.net> "James Kuyper Jr." <kuy...@wizard.net>
> writes:
> > ...
> > > >How does the behavior cease to be defined by the original source code,
> > > >just because the source code no longer exists?
> > >
> > > How can a non-existing entity define anything at all?
> >
> > By having been in existence at the time it needed to exist, in order to
> > define the behavior.
>
> This is starting to sound like:
> "If a tree falls in a forest with no ear to hear it..."

Exactly. The realist claims that the sound exists, whether or not anyone
hears it. I've never seen any point in Bishop Berkeley's take on the
issue. I understand his point, incidentally: all we really know are our
perceptions; it's inherently impossible to know what the causes of our
perceptions are; the best we can do is guess, and require that our
guesses be internally consistent, as well as being consistent with the
perceptions they're intended to explain. However, I don't see any point
in worrying about it; if you can't tell whether you're being fooled by a
Divinely perfect simulation of a non-existent external reality, knowing
that you might be being fooled doesn't do you any good; there's no
useful decisions that can be made based upon that awareness.
If you have no idea what I'm talking about, you might want to read up on
Bishop Berkeley, and what he was talking about when he posed that
question. He makes my worst bouts of pedantry sound practically normal,
by comparison.

> If I email an object module to you, and claim that it is conformant and
> exhibits always defined behavior, and then you link a program with it, is
> the behavior of the program defined?

Only if your claim was correct. What matters is whether or not the
behavior is defined, not whether you know that it's defined, and not
whether or not you can verify that it is defined. If the behavior was
defined when the source code existed, removing the code only removes the
ability to verify it; it doesn't change the fact that it was defined.

If I send you a kitten, and claim that it's father had black hair, does
the truth (or falsity) of my statement depend upon whether or not any
evidence survives to prove it (or disprove it)? I you say "yes", then
your concept of what "truth" means is too incompatible with mine, to
allow for coherent conversation (which would explain a lot about this
thread).

> Is the memory of the programmer "This thing has no undefined behavior that I
> recall" enough to make the behavior defined?

Only if that memory was correct.

> Must defined behavior be verifiable, or is a memory enough to make it so?

No - defined behavior exists, whether or not it is verifiable, just like
just about every other feature of reality. My wife exists (or doesn't
:-), regardless of whether or not you can verify the fact.

> If a memory that a program was well defined is enough, do we even need to
> examine source code to determine correctness? Maybe we should all delete
> our source code after the apps ship.
> ;-)

No, examining source code is precisely what you want to do to determine
whether it's correct. However, it's correct, or not, completely
independent of whether or not anyone ever does verify the fact; in fact,
it's independent of whether or not anyone could verify the fact.

It is loading more messages.
0 new messages