Re: Linux X demo

Discussion in 'C Programming' started by Herbert Kleebauer, Jul 21, 2007.

  1. "T.M. Sommers" wrote:
    > Rod Pemberton wrote:


    > >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}


    > > I.e., assuming LALR(1) and applying precedence, the above is:
    > > case 0x05:
    > > {
    > > --j;
    > > la[j] = la[j] / la[j+1];
    > > break;
    > > }
    > >
    > > It appears that DJGPP (GCC) works properly while OpenWatcom v1.3 fails. I'd
    > > guess that most K&R style compilers work.

    >
    > The origial line invokes undefined behavior; anything the
    > compiler does is "proper".


    Then you have a very bizarre definition of "proper". It isn't a
    problem when the behaviour for such a construct is undefined in the
    C specification. The problem arises when an implementation of the C
    specification defines the behaviour for this construct. If the
    behaviour would still be undefined in the implementation, then
    the compiler would emit an error message an stop if it encounter
    this construct. It would be also no problem if all compilers would
    implement the same behaviour (and so extend the C specification
    in a consistent manner). But just to define the behaviour in the
    implementation (which isn't defined in the specification) and only
    emit a warning is a serious bug. At least the compiler should give
    an error message, even when all warnings are disabled.

    C is a very simple to use language (at least in the old K&R form).
    You don't have to "learn" it, looking at a few simple examples is
    enough to get you started. But how should you get aware of the
    problem with a construct like "la[--j] = la[j] / la[j+1];" if
    it exactly does what you suppose it to do with the compiler you
    use? I only noticed this problem when I compiled a program on a
    SUN and it didn't work properly. And as you see from this thread,
    even I'm now aware of the problem, this types of construct are
    still in the code I wrote a long time ago.


    Cross posted to comp.compilers and comp.lang.c (somebody has
    to tell them, that they should implement a proper error
    reporting routine in there compilers).

    Followup-To set to alt.lang.asm
    Herbert Kleebauer, Jul 21, 2007
    #1
    1. Advertising

  2. I've posted this only to comp.lang.c, with no followups set, because
    my remarks are not particularly relevant to comp.compilers or
    alt.lang.asm.

    Herbert Kleebauer <> writes:
    > "T.M. Sommers" wrote:
    >> Rod Pemberton wrote:
    >> >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}

    >
    >> > I.e., assuming LALR(1) and applying precedence, the above is:
    >> > case 0x05:
    >> > {
    >> > --j;
    >> > la[j] = la[j] / la[j+1];
    >> > break;
    >> > }
    >> >
    >> > It appears that DJGPP (GCC) works properly while OpenWatcom v1.3
    >> > fails. I'd guess that most K&R style compilers work.

    >>
    >> The origial line invokes undefined behavior; anything the
    >> compiler does is "proper".

    >
    > Then you have a very bizarre definition of "proper". It isn't a
    > problem when the behaviour for such a construct is undefined in the
    > C specification. The problem arises when an implementation of the C
    > specification defines the behaviour for this construct.


    The original code exhibits undefined behavior as far as the standard
    is concerned because it violates the requirement in 6.5p2:

    Between the previous and next sequence point an object shall have
    its stored value modified at most once by the evaluation of an
    expression. Furthermore, the prior value shall be read only to
    determine the value to be stored.

    The original expression modifies j and reads the prior value of j for
    a purpose other than determining the value to be stored.

    > If the
    > behaviour would still be undefined in the implementation, then
    > the compiler would emit an error message an stop if it encounter
    > this construct. It would be also no problem if all compilers would
    > implement the same behaviour (and so extend the C specification
    > in a consistent manner). But just to define the behaviour in the
    > implementation (which isn't defined in the specification) and only
    > emit a warning is a serious bug. At least the compiler should give
    > an error message, even when all warnings are disabled.


    I'm not aware of any C compiler that bothers defines the behavior of
    this kind of construct. I suppose a compiler that imposes a strict
    order of evaluation might do so; such a compiler could give more
    consistent results at the expense of losing opportunities for
    optimization.

    There is *no* requirement in the standard for a compiler to issue a
    diagnostic for instances of undefined behavior. Most compilers will
    issue warnings in *some* such cases, but doing so in all cases is
    infeasible, and likely impossible (unless it just issues a warning for
    everything that *might* invoke undefined behavior).

    For example, this:

    int i;
    /* ... */
    i = i++;

    is a well-known case of undefined behavior, and many compilers will
    warn about it, though they're not required to. But this:

    int *p0, *p1;
    /* ... */
    *p0 = (*p1)++;

    invokes behavior *only* if p0==p1 when it's evaluated. There's
    typically no way to determine that kind of thing at compile time (if
    there were, we wouldn't need to run the program).

    > C is a very simple to use language (at least in the old K&R form).
    > You don't have to "learn" it, looking at a few simple examples is
    > enough to get you started. But how should you get aware of the
    > problem with a construct like "la[--j] = la[j] / la[j+1];" if
    > it exactly does what you suppose it to do with the compiler you
    > use? I only noticed this problem when I compiled a program on a
    > SUN and it didn't work properly. And as you see from this thread,
    > even I'm now aware of the problem, this types of construct are
    > still in the code I wrote a long time ago.


    You learn about such things by learning the language, which, as it
    turns out, is not as simple as you seem to think it is.

    > Cross posted to comp.compilers and comp.lang.c (somebody has
    > to tell them, that they should implement a proper error
    > reporting routine in there compilers).
    >
    > Followup-To set to alt.lang.asm


    See above.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jul 22, 2007
    #2
    1. Advertising

  3. On Jul 21, 5:19 pm, Herbert Kleebauer <> wrote:
    > "T.M. Sommers" wrote:
    > > Rod Pemberton wrote:
    > > >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}
    > > > I.e., assuming LALR(1) and applying precedence, the above is:
    > > > case 0x05:
    > > > {
    > > > --j;
    > > > la[j] = la[j] / la[j+1];
    > > > break;
    > > > }

    >
    > > > It appears that DJGPP (GCC) works properly while OpenWatcom v1.3 fails. I'd
    > > > guess that most K&R style compilers work.

    >
    > > The origial line invokes undefined behavior; anything the
    > > compiler does is "proper".

    >
    > Then you have a very bizarre definition of "proper".


    What's bizarre about it? "proper" in this context means something
    along the lines of "doing what it's supposed to do". The specification
    of the C language says that when a compiler comes across invalid code
    like this it can do whatever it chooses, so whatever the compiler
    chooses to do is "proper".

    >...
    >
    > C is a very simple to use language (at least in the old K&R form).
    > You don't have to "learn" it, looking at a few simple examples is
    > enough to get you started. But how should you get aware of the
    > problem with a construct like "la[--j] = la[j] / la[j+1];" if
    > it exactly does what you suppose it to do with the compiler you
    > use?


    This is a remarkably silly argument. You claim that C is so simple
    that you don't need to learn it, then complain that it has a feature
    that you wouldn't know about if you didn't learn the language
    properly. It's obvious that your claim is wrong.

    > Cross posted to comp.compilers and comp.lang.c (somebody has
    > to tell them, that they should implement a proper error
    > reporting routine in there compilers).
    >
    > Followup-To set to alt.lang.asm


    Posted to comp.lang.c, followup ignored and cleared. I don't see what
    this thread has to do with alt.lang.asm or comp.compilers.
    J. J. Farrell, Jul 22, 2007
    #3
  4. Keith Thompson wrote:


    > >> >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}


    > The original code exhibits undefined behavior as far as the standard
    > is concerned because it violates the requirement in 6.5p2:
    >
    > Between the previous and next sequence point an object shall have
    > its stored value modified at most once by the evaluation of an
    > expression. Furthermore, the prior value shall be read only to
    > determine the value to be stored.
    >
    > The original expression modifies j and reads the prior value of j for
    > a purpose other than determining the value to be stored.


    I know, but the question was, why doesn't the compiler emit an
    error message, when the source code obviously violates a required
    rule: the prior value __SHALL__ be read only to
    determine the value to be stored.



    > I'm not aware of any C compiler that bothers defines the behavior of
    > this kind of construct.


    By generating code for such a construct it DEFINES the behavior of
    the construct.


    > warn about it, though they're not required to. But this:
    >
    > int *p0, *p1;
    > /* ... */
    > *p0 = (*p1)++;
    >
    > invokes behavior *only* if p0==p1 when it's evaluated. There's
    > typically no way to determine that kind of thing at compile time (if
    > there were, we wouldn't need to run the program).


    That doesn't make any sense. You say, if the compiler processes
    a statement like "i=n/m;" it doesn't know whether the variable m=0 or
    not at run time and therefore has to compile it without an error
    message (which is pretty obvious). But then you make the conclusion
    that it also shouldn't generate an error message for "i=n/0" because
    this is only a special case of the general form "i=n/m" which is
    processed without an error message.


    > You learn about such things by learning the language, which, as it
    > turns out, is not as simple as you seem to think it is.


    Especially when the error reporting system of the C compiler
    is buggy and doesn't report code which violates the specification.
    Herbert Kleebauer, Jul 22, 2007
    #4
  5. "J. J. Farrell" wrote:
    > On Jul 21, 5:19 pm, Herbert Kleebauer <> wrote:



    > What's bizarre about it? "proper" in this context means something
    > along the lines of "doing what it's supposed to do". The specification
    > of the C language says that when a compiler comes across invalid code
    > like this it can do whatever it chooses, so whatever the compiler
    > chooses to do is "proper".


    Does the specification really say that the compiler can do what ever it
    likes when it is feed with invalid code? If so, then I would call this
    a bug in the specification. If a compiler is feed with invalid code,
    it has to generate an error message instead of compiling it to some
    freely chosen code.


    > > C is a very simple to use language (at least in the old K&R form).
    > > You don't have to "learn" it, looking at a few simple examples is
    > > enough to get you started. But how should you get aware of the
    > > problem with a construct like "la[--j] = la[j] / la[j+1];" if
    > > it exactly does what you suppose it to do with the compiler you
    > > use?

    >
    > This is a remarkably silly argument. You claim that C is so simple
    > that you don't need to learn it, then complain that it has a feature
    > that you wouldn't know about if you didn't learn the language
    > properly. It's obvious that your claim is wrong.


    Maybe it wouldn't be silly if you had completely read it. I said "enough
    to get you started". The problem are not features which you don't
    know when you don't learn them properly. The problem is, that
    statements like "la[--j] = la[j] / la[j+1];" behave differently
    when compiled with different compilers. If it would behave the
    same way on all compilers, you can learn it by "try and error".
    Herbert Kleebauer, Jul 22, 2007
    #5
  6. "Herbert Kleebauer" <> wrote in message
    news:...
    > Maybe it wouldn't be silly if you had completely read it. I said "enough
    > to get you started". The problem are not features which you don't
    > know when you don't learn them properly. The problem is, that
    > statements like "la[--j] = la[j] / la[j+1];" behave differently
    > when compiled with different compilers. If it would behave the
    > same way on all compilers, you can learn it by "try and error".
    >

    "Undefined behaviour" is a nuisance and it is used too broadly, to cover
    things like *(char *) rand() = 'x'; which would be very expensive to catch,
    and i = i++, which really should be tightened up.
    The first is a concession to runtime efficiency, the second a concession to
    compiler writers.
    The worst sort of undefined behaviour, as you say, is the sort that does
    what the programmer hoped it would.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Jul 22, 2007
    #6
  7. Herbert Kleebauer

    Flash Gordon Guest

    Herbert Kleebauer wrote, On 22/07/07 08:44:
    > "J. J. Farrell" wrote:
    >> On Jul 21, 5:19 pm, Herbert Kleebauer <> wrote:

    >
    >
    >> What's bizarre about it? "proper" in this context means something
    >> along the lines of "doing what it's supposed to do". The specification
    >> of the C language says that when a compiler comes across invalid code
    >> like this it can do whatever it chooses, so whatever the compiler
    >> chooses to do is "proper".

    >
    > Does the specification really say that the compiler can do what ever it
    > likes when it is feed with invalid code?


    For some types of invalid code, e.g. syntax errors, the compiler is
    required to issue a diagnostic, for other types, i.e. Undefined
    Behaviour, the standard places no requirements, i.e. *anything* is
    allowed. To quote from the standard:
    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
    2 NOTE Possible 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).
    3 EXAMPLE An example of undefined behavior is the behavior on
    integer overflow.


    > If so, then I would call this
    > a bug in the specification.


    You can call it what you like, but most people would not call it a bug
    because it is deliberate.

    > If a compiler is feed with invalid code,
    > it has to generate an error message instead of compiling it to some
    > freely chosen code.


    Others have stated why, in the general case, it is not necessarily
    possible to detect te undefined behaviour at compile time.

    >>> C is a very simple to use language (at least in the old K&R form).
    >>> You don't have to "learn" it, looking at a few simple examples is
    >>> enough to get you started. But how should you get aware of the
    >>> problem with a construct like "la[--j] = la[j] / la[j+1];" if
    >>> it exactly does what you suppose it to do with the compiler you
    >>> use?

    >> This is a remarkably silly argument. You claim that C is so simple
    >> that you don't need to learn it, then complain that it has a feature
    >> that you wouldn't know about if you didn't learn the language
    >> properly. It's obvious that your claim is wrong.

    >
    > Maybe it wouldn't be silly if you had completely read it. I said "enough
    > to get you started". The problem are not features which you don't
    > know when you don't learn them properly. The problem is, that
    > statements like "la[--j] = la[j] / la[j+1];" behave differently
    > when compiled with different compilers. If it would behave the
    > same way on all compilers, you can learn it by "try and error".


    No, the problem is that you think you can expect to get predictable
    results without learning the language properly. The simple fact is that
    if you don't learn a language properly you will get surprising
    differences in behaviour and this is not something that applies only to C.
    --
    Flash Gordon
    Flash Gordon, Jul 22, 2007
    #7
  8. Herbert Kleebauer

    Flash Gordon Guest

    Herbert Kleebauer wrote, On 22/07/07 08:44:
    > Keith Thompson wrote:
    >
    >>>>>>> case 0x05: {la[--j] = la[j] / la[j+1]; break;}

    >
    >> The original code exhibits undefined behavior as far as the standard
    >> is concerned because it violates the requirement in 6.5p2:
    >>
    >> Between the previous and next sequence point an object shall have
    >> its stored value modified at most once by the evaluation of an
    >> expression. Furthermore, the prior value shall be read only to
    >> determine the value to be stored.
    >>
    >> The original expression modifies j and reads the prior value of j for
    >> a purpose other than determining the value to be stored.

    >
    > I know, but the question was, why doesn't the compiler emit an
    > error message, when the source code obviously violates a required
    > rule: the prior value __SHALL__ be read only to
    > determine the value to be stored.


    Because it is not required to as has already been stated. It is also not
    possible to detect at compile time in the general case. Imagine the
    following code...
    /* Get value of i from user */
    /* Get value of j from user */
    z = z[j]++;

    Or i and j can be the result of some complex calculation.

    >> I'm not aware of any C compiler that bothers defines the behavior of
    >> this kind of construct.

    >
    > By generating code for such a construct it DEFINES the behavior of
    > the construct.


    Not necessarily, since processor manufacturers do not define the
    behaviour of all possible instructions or combinations of instructions,
    especially where they can perform parallel operations (i.e. most modern
    processors).

    >> warn about it, though they're not required to. But this:
    >>
    >> int *p0, *p1;
    >> /* ... */
    >> *p0 = (*p1)++;
    >>
    >> invokes behavior *only* if p0==p1 when it's evaluated. There's
    >> typically no way to determine that kind of thing at compile time (if
    >> there were, we wouldn't need to run the program).

    >
    > That doesn't make any sense. You say, if the compiler processes
    > a statement like "i=n/m;" it doesn't know whether the variable m=0 or
    > not at run time and therefore has to compile it without an error
    > message (which is pretty obvious). But then you make the conclusion
    > that it also shouldn't generate an error message for "i=n/0" because
    > this is only a special case of the general form "i=n/m" which is
    > processed without an error message.


    No, he said it is not required to.

    >> You learn about such things by learning the language, which, as it
    >> turns out, is not as simple as you seem to think it is.

    >
    > Especially when the error reporting system of the C compiler
    > is buggy and doesn't report code which violates the specification.


    Since it is not required to, you seem to be admitting that people are
    correct when they say you need to learn the language properly rather
    than by trial and error. So either learn the language properly or find a
    different language that meets your requirements.
    --
    Flash Gordon
    Flash Gordon, Jul 22, 2007
    #8
  9. Herbert Kleebauer <> writes:

    > Keith Thompson wrote:
    >
    >> >> >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}

    >
    >> The original code exhibits undefined behavior as far as the standard
    >> is concerned because it violates the requirement in 6.5p2:

    <snip>
    >> The original expression modifies j and reads the prior value of j for
    >> a purpose other than determining the value to be stored.

    >
    > I know, but the question was, why doesn't the compiler emit an
    > error message,


    That question was answered by Keith Thompson. It is not possible
    (provably so) to detect such errors at compile time. Imposing a
    defined meaning on all such constructs would go against the ethos of
    C: that you don't have to pay for features you don't want. The
    compiler's freedom to optimise would be constrained for almost all
    expressions in order to give a defined meaning to a few that
    programmers can usually spot quite easily.

    >> I'm not aware of any C compiler that bothers defines the behavior of
    >> this kind of construct.

    >
    > By generating code for such a construct it DEFINES the behavior of
    > the construct.


    Not for any useful meaning of the word 'defines'. It does indeed define
    a meaning for that construct, in that program location, with the same
    cache contents, run in that environment, compiled for that one machine
    by compiler version 6.5.4.3.2.1 patch level 0 linked with
    library... and so on.

    >> warn about it, though they're not required to. But this:
    >>
    >> int *p0, *p1;
    >> /* ... */
    >> *p0 = (*p1)++;
    >>
    >> invokes behavior *only* if p0==p1 when it's evaluated. There's
    >> typically no way to determine that kind of thing at compile time (if
    >> there were, we wouldn't need to run the program).

    >
    > That doesn't make any sense. You say, if the compiler processes
    > a statement like "i=n/m;" it doesn't know whether the variable m=0 or
    > not at run time and therefore has to compile it without an error
    > message (which is pretty obvious). But then you make the conclusion
    > that it also shouldn't generate an error message for "i=n/0" because
    > this is only a special case of the general form "i=n/m" which is
    > processed without an error message.


    I did not read KT's message as suggesting that a compiler should not
    try. I can't see where you get that from. He *did* say that the
    standard can't insist that a diagnostic be generated, and that is
    quote logical. The standard can't insist the compiler do something
    impossible. If you would like the standard to require a diagnostic in
    some simple cases, then you can suggest that, but I think you will be
    told that the role of the standard is to specify only the minimum that
    is required from an implementation.

    >> You learn about such things by learning the language, which, as it
    >> turns out, is not as simple as you seem to think it is.

    >
    > Especially when the error reporting system of the C compiler
    > is buggy and doesn't report code which violates the specification.


    There is no bug. I think you know this. Try reporting it to your
    compiler supplier and see what they say.

    You might also like to try better tools. The line in question produces:

    ub.c:8: warning: operation on ‘j’ may be undefined

    from gcc if you ask it give you lots of help (-Wall) and from splint I get:

    ub.c: (in function main)
    ub.c:8:14: Expression has undefined behavior (left operand modifies j, used by
    right operand): la[--j] = la[j] / la[j + 1]
    Code has unspecified behavior. Order of evaluation of function parameters or
    subexpressions is not defined, so if a value is used and modified in
    different places not separated by a sequence point constraining evaluation
    order, then the result of the expression is unspecified. (Use -evalorder to
    inhibit warning)

    --
    Ben.
    Ben Bacarisse, Jul 22, 2007
    #9
  10. Herbert Kleebauer

    pete Guest

    Herbert Kleebauer wrote:
    >
    > Keith Thompson wrote:
    >
    > > >> >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}

    >
    > > The original code exhibits undefined behavior as far as the standard
    > > is concerned because it violates the requirement in 6.5p2:
    > >
    > > Between the previous and next sequence point
    > > an object shall have
    > > its stored value modified at most once by the evaluation of an
    > > expression. Furthermore, the prior value shall be read only to
    > > determine the value to be stored.
    > >
    > > The original expression modifies j
    > > and reads the prior value of j for
    > > a purpose other than determining the value to be stored.

    >
    > I know, but the question was, why doesn't the compiler emit an
    > error message, when the source code obviously violates a required
    > rule: the prior value __SHALL__ be read only to
    > determine the value to be stored.
    >
    >
    >
    > > I'm not aware of any C compiler that bothers defines the behavior of
    > > this kind of construct.

    >
    > By generating code for such a construct it DEFINES the behavior of
    > the construct.


    That is insufficient for behavior definition.
    The generated code must also come with a guarantee
    that the same code
    will always be generated by that kind of construct.

    --
    pete
    pete, Jul 22, 2007
    #10
  11. Herbert Kleebauer <> writes:
    > Keith Thompson wrote:
    >> >> >>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}

    >
    >> The original code exhibits undefined behavior as far as the standard
    >> is concerned because it violates the requirement in 6.5p2:
    >>
    >> Between the previous and next sequence point an object shall have
    >> its stored value modified at most once by the evaluation of an
    >> expression. Furthermore, the prior value shall be read only to
    >> determine the value to be stored.
    >>
    >> The original expression modifies j and reads the prior value of j for
    >> a purpose other than determining the value to be stored.

    >
    > I know, but the question was, why doesn't the compiler emit an
    > error message, when the source code obviously violates a required
    > rule: the prior value __SHALL__ be read only to
    > determine the value to be stored.


    First off, who says it doesn't emit an error message? gcc, with no
    options specified, doesn't produce any diagnostics, but with the right
    options it prints:

    c.c:6: warning: operation on `j' may be undefined

    Probably other compilers behave similarly.

    Yes, it's a warning, not an error message, but the standard makes no
    distinction between different kinds of diagnostics, and as a
    programmer you should usually treat both the same way, as an
    indication that you need to fix the code.

    The rule I quoted does use the word "shall", but it's not part of a
    constraint. Any violation of a "shall" requirement outside a
    constraint invokes undefined behavior; the standard says so
    explicitly. Diagnostics are required for syntax errors and constraint
    violations. The code we're discussing is neither.

    >> I'm not aware of any C compiler that bothers defines the behavior of
    >> this kind of construct.

    >
    > By generating code for such a construct it DEFINES the behavior of
    > the construct.


    No, it really doesn't. As pete pointed out, by generating code it
    makes absolutely no guarantee that it will generate the same code
    again the next time you compile it.

    An implementation can define the behavior of some construct (that's
    not already defined by the standard) *only* by documenting it. If the
    implementation behaves in a certain way but hasn't documented that
    behavior, you can't rely on it; the authors can freely change the
    behavior in the next release, and quietly break your code. If the
    implementation's documentation makes a promise that the compiler fails
    to keep, that's a genuine bug, and you should report it.

    You *can't* learn the language, or even the charactistics of a
    particular implementation, entirely by trial and error.

    >> warn about it, though they're not required to. But this:
    >>
    >> int *p0, *p1;
    >> /* ... */
    >> *p0 = (*p1)++;
    >>
    >> invokes behavior *only* if p0==p1 when it's evaluated. There's


    Sorry, I meant "invokes undefined behavior".

    >> typically no way to determine that kind of thing at compile time (if
    >> there were, we wouldn't need to run the program).

    >
    > That doesn't make any sense. You say, if the compiler processes
    > a statement like "i=n/m;" it doesn't know whether the variable m=0 or
    > not at run time and therefore has to compile it without an error
    > message (which is pretty obvious).


    Right.

    > But then you make the conclusion
    > that it also shouldn't generate an error message for "i=n/0" because
    > this is only a special case of the general form "i=n/m" which is
    > processed without an error message.


    I didn't say that it *shouldn't* generate an error message; I said
    that it isn't *required* to do so.

    For any case of undefined behavior (n/m, where m might be zero, is a
    good example), there will be cases where the compiler potentially can
    *know* that it invokes UB:

    int n = 1;
    const int m = 0;
    n/m;

    cases where the compiler potentially can know that it doesn't:

    int n = /* whatever */;
    int m = /* whatever */;
    if (m != 0) [
    n/m;
    }

    (Note that since m != 0, n/m can't divide by zero -- but it *can*
    overflow if n == INT_MIN, m == -1, and INT_MIN < -INT_MAX.)

    and cases where it just can't tell:

    int n = atoi(argv[1]);
    int m = atoi(argv[2]);
    n/m;

    If you want to require diagnostics for the "obvious" cases, the
    authors of the C standard would have to have defined unambiguously
    which cases are "obvious" and which are not. They would have had to
    decide how much dataflow analysis to require, among other things. The
    amount of such analysis that's practical has varied considerably over
    time (the C language, in various forms, is over 30 years old, and
    compiler technology has advanced considerably in that time).

    So the authors of the standard did the simplest thing they could do:
    they didn't require *any* compile-time analysis behond what's required
    to process correct programs and issue diagnostics for syntax errors
    and constraint violations, and they defined all the actual constraints
    so that violations can be detected straightforwardly at compilation
    time. Requiring more than that would have (a) placed an additional
    burden on compiler writers, (b) made the language definition more
    complex and more error-prone (there are already known errors in the
    standard; making it more complex would inevitably have caused more
    errors, making the standard less reliable and less useful), and (c)
    wouldn't completely solve any problem anyway, because there will
    *always* be cases that can't be determined during compilation.

    *And* they permitted compilers to issue any additional diagnostics
    they like, so that a sufficiently clever compiler *can* do whatever
    additional analysis is necessary to detect and diagnose more instances
    of undefined behavior.

    >> You learn about such things by learning the language, which, as it
    >> turns out, is not as simple as you seem to think it is.

    >
    > Especially when the error reporting system of the C compiler
    > is buggy and doesn't report code which violates the specification.


    The code invokes undefined behavior. It doesn't violate the
    specification, it just isn't covered by it. And the authors of the
    standard were kind enough to *define* the areas of undefined behavior.

    If you want to see what the standard itself actually says, you might
    consider downloading
    <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf>. It's a
    post-C99 version of the standard, incorporating two Technical
    Corrigenda. You'll need to be aware that most compilers these days
    fully support the C90 standard, but very few fully support C99.

    I don't believe that any useful language can entirely avoid these
    issues. There are languages that have fewer instances of "undefined
    behavior" (or whatever the equivalent term is) than C does. This can
    be done by nailing down the behavior of constructs that C leaves
    undefined, or by not providing problematic features such as pointer
    arithmetic.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jul 22, 2007
    #11
  12. Herbert Kleebauer

    Chris Dollin Guest

    Herbert Kleebauer wrote:

    > "J. J. Farrell" wrote:
    >> On Jul 21, 5:19 pm, Herbert Kleebauer <> wrote:

    >
    >> What's bizarre about it? "proper" in this context means something
    >> along the lines of "doing what it's supposed to do". The specification
    >> of the C language says that when a compiler comes across invalid code
    >> like this it can do whatever it chooses, so whatever the compiler
    >> chooses to do is "proper".

    >
    > Does the specification really say that the compiler can do what ever it
    > likes when it is feed with invalid code?


    No, it says that the result of executing a construct for which the
    behaviour is undefined is completely at the whim of the implementation
    (not just the compiler, the entire implementation).

    Code that's invalid because of syntax errors or constraint violations
    is required to generate a diagnostic. (The compiler is free to abandon
    or continue processing; the resulting code can do anything it likes.)

    Having the compiler detect all cases of undefined behaviour is
    impossible [1], so it would be unreasonable for the standard to require it.
    Having the run-time detect all such cases would demand significant
    overheads; given the goals of C, it would be unreasonable for the
    standard to require it.

    Implementations are free to compete on the quality of their non-mandated
    diagnostics.

    [1] Does `*pointerToInt = someInteger++;` fall prey to undefined behaviour?

    --
    Chris "actual, not definitional" Dollin

    Hewlett-Packard Limited registered office: Cain Road, Bracknell,
    registered no: 690597 England Berks RG12 1HN
    Chris Dollin, Jul 23, 2007
    #12
  13. Herbert Kleebauer

    Richard Bos Guest

    Herbert Kleebauer <> wrote:

    > "J. J. Farrell" wrote:
    > > On Jul 21, 5:19 pm, Herbert Kleebauer <> wrote:

    >
    > > What's bizarre about it? "proper" in this context means something
    > > along the lines of "doing what it's supposed to do". The specification
    > > of the C language says that when a compiler comes across invalid code
    > > like this it can do whatever it chooses, so whatever the compiler
    > > chooses to do is "proper".

    >
    > Does the specification really say that the compiler can do what ever it
    > likes when it is feed with invalid code? If so, then I would call this
    > a bug in the specification. If a compiler is feed with invalid code,
    > it has to generate an error message instead of compiling it to some
    > freely chosen code.


    Please draw up a specification of "invalid code" which does not require
    the compiler to solve the Halting Problem.

    Richard
    Richard Bos, Jul 23, 2007
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Song
    Replies:
    0
    Views:
    565
  2. F. GEIGER
    Replies:
    9
    Views:
    1,213
    F. GEIGER
    May 3, 2004
  3. C GIllespie

    wxpython demo under linux

    C GIllespie, May 12, 2004, in forum: Python
    Replies:
    2
    Views:
    478
    Sion Arrowsmith
    May 12, 2004
  4. Andy Leszczynski

    wxPython demo /Process does not open new demo

    Andy Leszczynski, Feb 18, 2005, in forum: Python
    Replies:
    1
    Views:
    636
    Andy Leszczynski
    Feb 18, 2005
  5. santosh

    Re: Linux X demo

    santosh, Jul 20, 2007, in forum: C Programming
    Replies:
    8
    Views:
    342
    Malcolm McLean
    Jul 20, 2007
Loading...

Share This Page