Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #71454 > unrolled thread

Re: the language (and the role of Undefined Behavior therein)

Started bysupercat@casperkitty.com
First post2015-09-29 15:48 -0700
Last post2015-10-19 16:11 -0700
Articles 9 on this page of 29 — 7 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-09-29 15:48 -0700
    Re: the language (and the role of Undefined Behavior therein) Tim Rentsch <txr@alumni.caltech.edu> - 2015-10-04 16:57 -0700
      Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-04 19:48 -0700
        Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-10-05 04:50 +0000
          Re: the language (and the role of Undefined Behavior therein) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-05 13:43 +0100
            Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-10-05 15:26 +0000
              Re: the language (and the role of Undefined Behavior therein) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-05 19:39 +0100
                Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-05 13:32 -0700
                Re: the language (and the role of Undefined Behavior therein) glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-10-05 22:06 +0000
                  Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-05 16:08 -0700
                  Re: the language (and the role of Undefined Behavior therein) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-06 11:04 +0100
                    Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-06 08:06 -0700
                      Re: the language (and the role of Undefined Behavior therein) Rosario19 <Ros@invalid.invalid> - 2015-10-06 18:14 +0200
                        Re: the language (and the role of Undefined Behavior therein) Rosario19 <Ros@invalid.invalid> - 2015-10-06 18:54 +0200
                          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-06 11:20 -0700
                        Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-06 10:00 -0700
                      Re: the language (and the role of Undefined Behavior therein) David Thompson <dave.thompson2@verizon.net> - 2015-10-31 06:44 -0400
                        Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-31 11:08 -0700
                          Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-10-31 13:53 -0700
                            Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-31 14:06 -0700
            Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-05 09:28 -0700
            Re: the language (and the role of Undefined Behavior therein) Keith Thompson <kst-u@mib.org> - 2015-10-05 11:20 -0700
              Re: the language (and the role of Undefined Behavior therein) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-05 20:13 +0100
                Re: the language (and the role of Undefined Behavior therein) Tim Rentsch <txr@alumni.caltech.edu> - 2015-10-12 09:29 -0700
        Re: the language (and the role of Undefined Behavior therein) Tim Rentsch <txr@alumni.caltech.edu> - 2015-10-12 10:32 -0700
          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-12 12:23 -0700
          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-12 14:42 -0700
          Re: the language (and the role of Undefined Behavior therein) supercat@casperkitty.com - 2015-10-14 09:10 -0700
            Re: the language (and the role of Undefined Behavior therein) Tim Rentsch <txr@alumni.caltech.edu> - 2015-10-19 16:11 -0700

Page 2 of 2 — ← Prev page 1 [2]


#71981

Fromsupercat@casperkitty.com
Date2015-10-05 09:28 -0700
Message-ID<44bec12a-a168-43c1-81b5-db64def1ac76@googlegroups.com>
In reply to#71968
On Monday, October 5, 2015 at 7:44:05 AM UTC-5, Ben Bacarisse wrote:
> In his or her uint32_t w = *(uint32_t *)p; example I suspect that
> supercat would be fine with a trap if p is misaligned, or if the result
> was some odd data that comes from reading the nearest whole word.  The
> objection (which I don't share) is that the result can be to cue the
> optimiser to do something unexpected.

I would *expect* that attempting to read data from a misaligned pointer
may trap on platforms which are not documented as supporting such accesses
for *all* instructions without exception [e.g. even though Cortex-M3 will
automatically handle an "LDR" of an unaligned address by performing two
half-word loads, or else two byte loads and a half-word load, I would
not find it surprising if a compiler were to generate code for:

    x=foo[0]; y=foo[1]; z=foo[2];

which uses an "LDRMIA" instruction that traps on unaligned addresses.]

> I don't share it because it's a rare situation with many solutions.  The
> obvious one being to copy the target's representation using a char * or
> memcpy.

Decomposing things into discrete unsigned char values is not impossible, but
in cases where one knows that data will be aligned to a larger type using
a larger type may make code significantly more efficient (especially if the
programmer knows more about the type's alignment than the compiler).  While
optimizers are smarter than they used to be, I think there is something wrong
with the idea that even if an older compiler would generate code for
something like:

    // Store to "dest" 1024 bytes of data xor'ed from "s1" and "s2", if
    // all pointers are known to be word-aligned.

    uint32_t *wd = (uint32_t*)dest;
    uint32_t *w1 = (uint32_t*)s1;
    uint32_t *w2 = (uint32_t*)s2;

    for (unsigned int i=0; i<256; i++)
      wd[i] = w1[i] ^ w2[i];

which would meets a programmer's requirements perfectly, in cases where
that might result in type punning which the Standard does not require that
compilers accept, it's better to have the programmer write the code some
other way and hope the optimizer is able to figure out that it can generate
the same code as the old compiler could do with no trouble at all, than it
would be to have compilers process the code with the same semantics that
compilers throughout the 1990s would have done.

[toc] | [prev] | [next] | [standalone]


#71995

FromKeith Thompson <kst-u@mib.org>
Date2015-10-05 11:20 -0700
Message-ID<lny4fh41pf.fsf@kst-u.example.com>
In reply to#71968
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
[...]
> I don't think that's not really addressing supercat's point.  The
> effective type rule renders some accesses undefined, and that is used by
> some implementations to do what is, to some, surprising things -- like
> not doing the access at all.  K&R 1st ed. had a notable phrase about
> pointer conversions which was something like "the result is not
> specified but should be unsurprising to anyone familiar with the
> underlying address structure".  I think he or she would like to go back
> to the days when the result of doing undefined things were largely
> unsurprising to people in the know.
[...]

It's actually about pointer-to-integer conversions.  It's in K&R1
Appendix A 14.4, page 210.

    A pointer may be converted to any of the integral types large enough
    to hold it.  Whether an int or a long is required is machine
    dependent.  The mapping function is also machine dependent, but is
    intended to be unsurprising to those who know the addressing
    structure of the machine.  Details for some particular machines are
    given below.

Later in the same section, it gives details for the PDP-11, Honeywell
6000, IBM 370, and Interdata 8/32.  (The address structure of the
Honeywell 6000 is peculiar by modern standards.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#71998

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-10-05 20:13 +0100
Message-ID<87r3l9jfh5.fsf@bsb.me.uk>
In reply to#71995
Keith Thompson <kst-u@mib.org> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> [...]
>> I don't think that's not really addressing supercat's point.  The
>> effective type rule renders some accesses undefined, and that is used by
>> some implementations to do what is, to some, surprising things -- like
>> not doing the access at all.  K&R 1st ed. had a notable phrase about
>> pointer conversions which was something like "the result is not
>> specified but should be unsurprising to anyone familiar with the
>> underlying address structure".  I think he or she would like to go back
>> to the days when the result of doing undefined things were largely
>> unsurprising to people in the know.
> [...]
>
> It's actually about pointer-to-integer conversions.  It's in K&R1
> Appendix A 14.4, page 210.
>
>     A pointer may be converted to any of the integral types large enough
>     to hold it.  Whether an int or a long is required is machine
>     dependent.  The mapping function is also machine dependent, but is
>     intended to be unsurprising to those who know the addressing
>     structure of the machine.  Details for some particular machines are
>     given below.

Thanks.  It seems it was a slightly less general remark than I recall,
but, given that sentiment, it's unlikely that K&R would have intended
any other pointer conversions to use a surprising mapping.

> Later in the same section, it gives details for the PDP-11, Honeywell
> 6000, IBM 370, and Interdata 8/32.  (The address structure of the
> Honeywell 6000 is peculiar by modern standards.)

I remember the Honeywell well.  I used B on one over a very slow
connection to the University of Aberdeen but that one did not run Unix
in those days.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#72629

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-10-12 09:29 -0700
Message-ID<kfn1td0m4nr.fsf@x-alumni2.alumni.caltech.edu>
In reply to#71998
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Keith Thompson <kst-u@mib.org> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> [...]
>>> I don't think that's not really addressing supercat's point.  The
>>> effective type rule renders some accesses undefined, and that is used by
>>> some implementations to do what is, to some, surprising things -- like
>>> not doing the access at all.  K&R 1st ed. had a notable phrase about
>>> pointer conversions which was something like "the result is not
>>> specified but should be unsurprising to anyone familiar with the
>>> underlying address structure".  I think he or she would like to go back
>>> to the days when the result of doing undefined things were largely
>>> unsurprising to people in the know.
>>
>> [...]
>>
>> It's actually about pointer-to-integer conversions.  It's in K&R1
>> Appendix A 14.4, page 210.
>>
>>     A pointer may be converted to any of the integral types large enough
>>     to hold it.  Whether an int or a long is required is machine
>>     dependent.  The mapping function is also machine dependent, but is
>>     intended to be unsurprising to those who know the addressing
>>     structure of the machine.  Details for some particular machines are
>>     given below.
>
> Thanks.  It seems it was a slightly less general remark than I recall,
> but, given that sentiment, it's unlikely that K&R would have intended
> any other pointer conversions to use a surprising mapping.

Even if conversions between various pointer types are meant to
work as one would expect, that isn't the same as saying accesses
are going to work also.  I don't see any reason to presume K&R
considered these two aspects synonymous.

[toc] | [prev] | [next] | [standalone]


#72650

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-10-12 10:32 -0700
Message-ID<kfnoag4kn5v.fsf@x-alumni2.alumni.caltech.edu>
In reply to#71919
supercat@casperkitty.com writes:

> On Sunday, October 4, 2015 at 6:57:39 PM UTC-5, Tim Rentsch wrote:
>> Two, if you want people to take you seriously, it's important to
>> become more conversant with the Standard and use its terminology
>> in the same way the Standard does.  Perhaps that shouldn't be
>> true but IME there is a significant effect.
>
> Fair point;  I think one of my difficulties is that I was
> programming in C before there even *was* an ANSI Standard,
> [snip elaboration]

So was I.  I adapted.  I'm sure you can if you put your mind to
it.

Let me offer a couple more suggestions.  One, limit the focus to
talk about only one problem at a time.  It seems like the threads
wander around to this problem or that problem, with some new
aspect popping up to confuse the issue.  Doing that is never
going to go anywhere positive.  Two, dial down the rhetoric.
Despite what you may think the people in WG14 are not a bunch of
lamebrains.  There is no point in speculating about the history
of how C got to where it is - deal with it where is now, because
like it or not that is the reality.  I think you need to decide
whether you want to accomplish something or whether you are just
going to complain about what a horrible language C is.  If all
you do is the latter then before too long your comments will be
falling on deaf ears (eg, the parable of the boy who cried wolf).

Oh, one more thing - for goodness sake stop saying 'typecast'.
In C the word is (and always has been) cast.

[toc] | [prev] | [next] | [standalone]


#72655

Fromsupercat@casperkitty.com
Date2015-10-12 12:23 -0700
Message-ID<7495960f-a049-493b-802c-e8b4887c8ad7@googlegroups.com>
In reply to#72650
On Monday, October 12, 2015 at 12:32:54 PM UTC-5, Tim Rentsch wrote:
> So was I.  I adapted.  I'm sure you can if you put your mind to
> it.

How would you suggest that performance-critical code which has a word aligned
*short and needs to write pairs of values should do so, if such values may
need to be passed to code over which has a recognized need to meet the same
requirement and over which the programmer has no control?

If the data creator uses a pointer to a union containing two shorts, two
uint16_t, two uint32_t, etc. and the recipient accesses the array using only
types listed in the first union, all will be fine.  If, however, the data recipient uses any union type other than the exact same union type used by
the creator, code will invoke Undefined Behavior.

Since the Standard doesn't define any unions comprising differently-sized
integers for that purpose, what reasonably-performant types could the
methods use without giving an implementation the right to do anything it
likes in any circumstance where data would the second method would see
data written in an incompatible type?

Likewise, how would you suggest that one write performance critical code
that needs to operate on an array of pointers to many different (and
unknown) kinds of structures?

Does C provide any way of declaring a pointer which can be used to read
and write any kind of pointer to a structure?  Since the C has from the
beginning mandated that all pointers to structures must have compatible
representations, there is no reason that any compiler should be unable
to support such a type, but so far as I can tell no such type exists.

> Let me offer a couple more suggestions.  One, limit the focus to
> talk about only one problem at a time.  It seems like the threads
> wander around to this problem or that problem, with some new
> aspect popping up to confuse the issue.  Doing that is never
> going to go anywhere positive.

Perhaps I need to start more new threads?  The newsreaders I used in the
1980s could do a good job of working with threads that forked, especially
when the subject line changed, but such ability doesn't seem to be so
common nowadays.

>                                           I think you need to decide
> whether you want to accomplish something or whether you are just
> going to complain about what a horrible language C is.

The version of C which is common to most compilers is a good language.  The
version which in which one can right strictly-conforming programs is not.

IMHO, a good standard should have the property that even if it is not
possible to use every standards-compliant X with every standards-compliant
Y, it should be possible to easily identify most combinations of X and Y
that will work together, with very few false positives [it would be
desirable if one could identify all compatible combinations, but that's
not nearly as important as avoiding false positives].

To what extent would you say that the C Standard has such a property?
Outside of the very small percentage of C programs that are strictly-
conforming, what the fact that an implementation is Standards-compliant
usefully say about which programs can be relied not to malfunction if
given to it?

[toc] | [prev] | [next] | [standalone]


#72658

Fromsupercat@casperkitty.com
Date2015-10-12 14:42 -0700
Message-ID<9d53c087-7628-4811-b70e-0d8060bf154a@googlegroups.com>
In reply to#72650
On Monday, October 12, 2015 at 12:32:54 PM UTC-5, Tim Rentsch wrote:
> Despite what you may think the people in WG14 are not a bunch of
> lamebrains.

The message I read from the C89 type-punning rationale is that the authors
of the Standard find code which does such things "dubious" and either

(1a) They were oblivious to the fact that it is not always possible to write
     code which complies with their new rules and is not slower, harder to
     read, or both.

(1b) They want code which works efficiently, but offends their sensibilities,
    to be replaced with code that is slower, harder to read, or both.

or else

(2)  They figured they could claim to be catering to compiler writers who
     were begging for optimization opportunities, but that nobody would
     actually take that horribly-written type punning rule seriously.

Being a charitable person, I would be inclined to lean toward #2.

Can you think of any other explanation which would suggest that the C
language would be better off if programmers and compiler writers pay
attention to the Committee rather than collectively ignoring it?

[toc] | [prev] | [next] | [standalone]


#72852

Fromsupercat@casperkitty.com
Date2015-10-14 09:10 -0700
Message-ID<35921b6c-bd97-48c2-8f59-886bbf03f4e0@googlegroups.com>
In reply to#72650
On Monday, October 12, 2015 at 12:32:54 PM UTC-5, Tim Rentsch wrote:
> So was I.  I adapted.  I'm sure you can if you put your mind to
> it.

Sorry if my earlier reply was somewhat inflammatory.  The unhelpfully
inflammatory language of the C89 rationale really raised my dander.  I
do not like being told that code I write the way it needs to be written
should not exist.

There are some kinds of code for which compliance with the Standard as
written is not practical.  Such things are especially common in systems
programming, which is the purpose for which C was originally designed.

Both semantics and performance could be greatly improved if the language
were to add a few features:

1. An macro that, if defined, would invoke an intrinsic which would accept a
   pointer and a size argument, evaluate each one an Unspecified number of
   times, and then behave in a fashion semantically equivalent to
   memmove((ptr),(ptr),(size)); but hopefully without wasting time actually
   moving anything.

2. A means by which a compiler could be required to at its option either
   compile the program without applying the new strict aliasing rules or
   else refuse compilation.
   
3. A directive which compilers would be free to ignore, but which if
   present at file scope would authorize the use of even stricter aliasing
   semantics for the balance of the translation unit, and if present in
   function scope, would authorize the use of even stricter aliasing
   semantics for the balance of the function, to wit:

       Every pointer shall only be used to read either an lvalue of a
       directly-compatible type, or data which has been explicitly
       subjected to the macro specified in (1).

4. Allow use of the "register" qualifier to global, static, or automatic
   variables to indicate that they may be safely cached in registers
   *except* when their address is passed to a function call, in which
   case the cached value must be flushed before the call, but may
   be re-cached afterward.

Would you agree that such semantics would be a major improvement over the
existing situation?

[toc] | [prev] | [next] | [standalone]


#73359

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-10-19 16:11 -0700
Message-ID<kfn37x6fo7d.fsf@x-alumni2.alumni.caltech.edu>
In reply to#72852
supercat@casperkitty.com writes:

> On Monday, October 12, 2015 at 12:32:54 PM UTC-5, Tim Rentsch wrote:
>> So was I.  I adapted.  I'm sure you can if you put your mind to
>> it.
>
> Sorry if my earlier reply was somewhat inflammatory.  The unhelpfully
> inflammatory language of the C89 rationale really raised my dander.  I
> do not like being told that code I write the way it needs to be written
> should not exist.
>
> There are some kinds of code for which compliance with the Standard as
> written is not practical.  Such things are especially common in systems
> programming, which is the purpose for which C was originally designed.
>
> Both semantics and performance could be greatly improved if the language
> were to add a few features:
>
> 1. An macro that, if defined, would invoke an intrinsic which would accept a
>    pointer and a size argument, evaluate each one an Unspecified number of
>    times, and then behave in a fashion semantically equivalent to
>    memmove((ptr),(ptr),(size)); but hopefully without wasting time actually
>    moving anything.
>
> 2. A means by which a compiler could be required to at its option either
>    compile the program without applying the new strict aliasing rules or
>    else refuse compilation.
>
> 3. A directive which compilers would be free to ignore, but which if
>    present at file scope would authorize the use of even stricter aliasing
>    semantics for the balance of the translation unit, and if present in
>    function scope, would authorize the use of even stricter aliasing
>    semantics for the balance of the function, to wit:
>
>        Every pointer shall only be used to read either an lvalue of a
>        directly-compatible type, or data which has been explicitly
>        subjected to the macro specified in (1).
>
> 4. Allow use of the "register" qualifier to global, static, or automatic
>    variables to indicate that they may be safely cached in registers
>    *except* when their address is passed to a function call, in which
>    case the cached value must be flushed before the call, but may
>    be re-cached afterward.
>
> Would you agree that such semantics would be a major improvement over the
> existing situation?

There have been several followup postings from you along
similar lines, to various things I've written, in several
different threads.  I'm not sure if you're expecting a
response from me or just riffing.  So, let me be clear about
my own choices here.  I don't want to enter into these kinds
of discussions in comp.lang.c.  If there is a topic that is
of particular interest to you, start a new thread for just
that topic in comp.std.c, and if I think I have something to
contribute I will respond there.  Okay?

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c


csiph-web