Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #83406 > unrolled thread
| Started by | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| First post | 2022-04-01 20:34 -0700 |
| Last post | 2022-04-11 15:11 -0700 |
| Articles | 20 on this page of 121 — 25 participants |
Back to article view | Back to comp.lang.c++
GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-01 20:34 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-04-02 10:19 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Bo Persson <bo@bo-persson.se> - 2022-04-02 12:19 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-02 14:18 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Christian Gollwitzer <auriocus@gmx.de> - 2022-04-02 12:30 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? David Brown <david.brown@hesbynett.no> - 2022-04-02 14:12 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Bonita Montero <Bonita.Montero@gmail.com> - 2022-04-02 14:20 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-02 14:28 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-02 17:27 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-02 15:39 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Barry Schwarz <schwarzb@delq.com> - 2022-04-02 09:15 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-04 08:21 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 12:02 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-04 14:42 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-04 08:49 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-05 15:18 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-05 08:37 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-05 15:54 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-06 11:24 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Juha Nieminen <nospam@thanks.invalid> - 2022-04-06 10:49 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-06 18:21 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2022-04-06 15:40 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-06 15:00 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2022-04-06 17:03 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2022-04-06 17:18 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-07 08:58 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-07 11:01 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-04-06 23:13 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-07 09:11 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-06 10:53 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-06 14:50 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation Sams Lara <samlara622@gmail.com> - 2022-04-06 22:27 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-04-06 14:51 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Sams Lara <samlara622@gmail.com> - 2022-04-06 22:59 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-04-06 15:54 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Öö Tiib <ootiib@hot.ee> - 2022-04-06 15:11 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-09 09:38 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-06 23:48 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-06 18:39 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-06 23:49 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-05 08:55 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-05 10:23 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-05 14:36 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-04 12:27 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-05 15:21 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-05 08:41 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-05 15:50 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-05 10:19 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-05 14:33 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-05 14:28 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 18:29 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-02 11:27 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-04 08:23 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 12:15 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-04 14:43 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 18:34 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-05 15:23 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-05 08:38 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-05 15:49 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-04-05 11:31 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation scott@slp53.sl.home (Scott Lurndal) - 2022-04-05 22:45 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-02 23:34 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation Manfred <noname@add.invalid> - 2022-04-03 17:43 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-03 15:40 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation Muttley@dastardlyhq.com - 2022-04-04 08:24 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-04 12:01 -0400
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-03 13:02 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-03 04:46 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Öö Tiib <ootiib@hot.ee> - 2022-04-03 07:02 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-03 11:30 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-03 21:20 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-03 12:49 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-04 00:40 +0300
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-03 15:40 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 09:13 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 09:02 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-04 02:07 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 13:28 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-04 06:01 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation David Brown <david.brown@hesbynett.no> - 2022-04-04 19:11 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation scott@slp53.sl.home (Scott Lurndal) - 2022-04-04 17:59 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-05 06:55 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation Manfred <noname@add.invalid> - 2022-04-03 18:39 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-03 09:09 +0300
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Manfred <noname@add.invalid> - 2022-04-02 19:53 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? David Brown <david.brown@hesbynett.no> - 2022-04-03 13:45 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Manfred <noname@add.invalid> - 2022-04-03 17:27 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-04-02 21:17 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Manfred <noname@invalid.add> - 2022-04-02 23:04 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-04-03 00:22 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-02 17:33 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-04-03 14:23 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-06 08:31 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-06 11:05 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-25 03:32 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-02 11:18 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? David Brown <david.brown@hesbynett.no> - 2022-04-02 13:11 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Manu Raju <MR@invalid.invalid> - 2022-04-02 18:26 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Manu Raju <MR@invalid.invalid> - 2022-04-02 21:46 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-02 17:35 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Language Lawyer <language.lawyer@gmail.com> - 2022-04-04 02:28 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-04 05:52 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Language Lawyer <language.lawyer@gmail.com> - 2022-06-21 03:36 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Juha Nieminen <nospam@thanks.invalid> - 2022-04-04 10:48 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-04 05:49 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Juha Nieminen <nospam@thanks.invalid> - 2022-04-05 06:34 +0000
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-04-05 10:20 +0100
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-05 07:51 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Manfred <noname@add.invalid> - 2022-04-05 17:53 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Christian Hanné <the.hanne@gmail.com> - 2022-04-10 06:06 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-09 21:20 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> - 2022-04-09 21:39 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-04-09 22:34 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Christian Hanné <the.hanne@gmail.com> - 2022-04-10 09:19 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? David Brown <david.brown@hesbynett.no> - 2022-04-10 12:21 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Christian Hanné <the.hanne@gmail.com> - 2022-04-10 12:47 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> - 2022-04-11 12:18 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-04-11 12:33 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Christian Hanné <the.hanne@gmail.com> - 2022-04-10 09:20 +0200
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> - 2022-04-11 12:32 -0700
Re: GCC hasn't even gotten around to sequencing argument evaluation yet??? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-11 15:11 -0700
Page 4 of 7 — ← Prev page 1 2 3 [4] 5 6 7 Next page →
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2022-04-05 22:45 +0000 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <TD33K.210663$OT%7.1445@fx07.iad> |
| In reply to | #83489 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>Muttley@dastardlyhq.com writes:
>> On Tue, 5 Apr 2022 08:38:16 -0700
>> Andrey Tarasevich <andreytarasevich@hotmail.com> wrote:
>>>On 4/5/2022 8:23 AM, Muttley@dastardlyhq.com wrote:
>>>"Test programs" don't demonstrate anything at all.
>>
>> So how would you demonstrate how a compiler treats some code then? Ask it?
>>
>> int main()
>> {
>> int i = 0;
>> i = i++ + ++i;
>> printf("%d\n",i);
>> return 0;
>> }
>>
>> The output with clang is 1, 2 with gcc. If what you said was correct the
>> result would be 0, an abort or some kind of compilation error.
>
>We're talking about what the standard *allows* compilers to do, whether
>any actual compiler takes advantage of that permission or not.
>
>The statement was that a compiler *can* replace `i = i++ + ++i;`
>with `__builtin_unreachable()`, not that it *must*.
And in any case, the 6 line program above doesn't exercise any
of the more sophisticated parts of the compiler. Include that
fragment in a 4000 line source file, add -O3, and who know what code it
may generate differently.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2022-04-02 23:34 -0400 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2b4k4$19d$1@dont-email.me> |
| In reply to | #83416 |
On 4/2/22 11:39, Muttley@dastardlyhq.com wrote:
...
> Undefined simply means no one cared enough to define it.
"undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of
erroneous data, for which this document imposes no requirements" (3.4.3p1).
Key point so pay attention to:
1. It's undefined if "this document" (the C standard) imposes no
requirements, even if some other document does impose requirements.
2. "No requirements" is far stronger than most people think, the
standard tries to make this clear with some examples:
"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.4.3p2)
Notice that undefined behavior can occur before the program even
executes, at compile time. The general rule is that, as soon as it would
otherwise become inevitable that code with undefined behavior would get
executed, the C standard ceases to impose any requirements on the
behavior of your program. This might occur LONG before that code gets
executed, and might have a consequence of not actually executing that code.
The standard also tell you how you can identify whether the behavior is
undefined:
"If a "shall" or "shall not" requirement that appears outside of a
constraint or runtime-constraint is violated, the behavior is undefined.
Undefined behavior is otherwise indicated in this document 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"." (4p2).
> The compiler writers
> would have to deliberately change their parameter parsing and stack pushing
> code in order to crash in this instance.
The most common way that undefined behavior has consequences is when it
enables an implementation to simplify an optimization, by not bothering
to worry about whether code might be written which has undefined
behavior. This means that the consequences of code with undefined
behavior can occur in places far removed from that code.
A famous example has the following structure:
if(p==NULL)
{
printf("p is null\n");
}
*p = 0;
Because the "*p = 0" expression would have undefined behavior if p were
NULL, then an implementation is free to assume that p is NOT null. As a
result, a fully conforming implementation of C can drop the the entire
if-statement - and this is an optimization that real compilers have
actually implemented.
>> POSIX, documented compiler features, etc.), then you can't rely on it
>> for any purpose.
>
> You can't rely on a rusty bicycle working, but its not going to shoot you in
> the head.
The ways in which real-world fully conforming implementations of C can
handle code with undefined behavior are much weirder and far harder to
predict than the ways a rusty bicycle can fail.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2022-04-03 17:43 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2cfbg$18rh$1@gioia.aioe.org> |
| In reply to | #83428 |
On 4/3/2022 5:34 AM, James Kuyper wrote:
> On 4/2/22 11:39, Muttley@dastardlyhq.com wrote:
> ...
>> Undefined simply means no one cared enough to define it.
>
> "undefined behavior
> behavior, upon use of a nonportable or erroneous program construct or of
> erroneous data, for which this document imposes no requirements" (3.4.3p1).
Note that this is the definition in the C standard. The C++ standard
(since we're in c.l.c++) makes it more abrupt (n4659, 3.27):
"undefined behavior
behavior for which this International Standard imposes no requirements"
Followed by a note containing a plethora of sentences arguably hardly
clarifying anything (IMO)
> [...]
However, your conclusion is right:
>
> The ways in which real-world fully conforming implementations of C can
> handle code with undefined behavior are much weirder and far harder to
> predict than the ways a rusty bicycle can fail.
>
In short: if your program is supposed to work, you need to ensure that
it never runs into undefined behavior. Never.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2022-04-03 15:40 -0400 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2ct70$vr2$1@dont-email.me> |
| In reply to | #83436 |
On 4/3/22 11:43, Manfred wrote: > On 4/3/2022 5:34 AM, James Kuyper wrote: >> On 4/2/22 11:39, Muttley@dastardlyhq.com wrote: >> ... >>> Undefined simply means no one cared enough to define it. >> >> "undefined behavior >> behavior, upon use of a nonportable or erroneous program construct or of >> erroneous data, for which this document imposes no requirements" (3.4.3p1). > > Note that this is the definition in the C standard. The C++ standard > (since we're in c.l.c++) makes it more abrupt (n4659, 3.27): My apologies - I reference both standards frequently enough that I sometimes grab the wrong one. ... >> The ways in which real-world fully conforming implementations of C can >> handle code with undefined behavior are much weirder and far harder to >> predict than the ways a rusty bicycle can fail. >> > > In short: if your program is supposed to work, you need to ensure that > it never runs into undefined behavior. Never. I wouldn't put it that strongly - one of the key reasons why many things have undefined behavior is that it enables extensions to C++. If the behavior is undefined by the C++ standard, but defined by some other document (such as POSIX, or your implementation's documentation), there's no problem with writing code they relies upon what it says in that other document, so long as that document has authority over all of the systems where you will need it. But make sure that there actually is such a document, and make sure that you know what it actually says. The example I gave was due to people thinking that the documented behavior of dereferencing a null pointer was to safely retrieve whatever was stored at memory address 0, since that's what the hardware does. But C is NOT an assembler. It's not the hardware's definition of the behavior that's relevant, it's the compiler's, and the compiler documented that the behavior of dereferencing a pointer (of any value, null or not) was to enable optimizations based upon the assumption that the pointer could not be null. This optimization was optional, and the people who wrote that code had the option turned on.
[toc] | [prev] | [next] | [standalone]
| From | Muttley@dastardlyhq.com |
|---|---|
| Date | 2022-04-04 08:24 +0000 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2ea07$sgm$1@gioia.aioe.org> |
| In reply to | #83428 |
On Sat, 2 Apr 2022 23:34:28 -0400 James Kuyper <jameskuyper@alumni.caltech.edu> wrote: >On 4/2/22 11:39, Muttley@dastardlyhq.com wrote: >.... >> Undefined simply means no one cared enough to define it. > >"undefined behavior >behavior, upon use of a nonportable or erroneous program construct or of >erroneous data, for which this document imposes no requirements" (3.4.3p1). > >Key point so pay attention to: >1. It's undefined if "this document" (the C standard) imposes no >requirements, even if some other document does impose requirements. How does that differ to what I said?
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2022-04-04 12:01 -0400 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2f4ol$v7e$1@dont-email.me> |
| In reply to | #83451 |
On 4/4/22 04:24, Muttley@dastardlyhq.com wrote:
> On Sat, 2 Apr 2022 23:34:28 -0400
> James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>> On 4/2/22 11:39, Muttley@dastardlyhq.com wrote:
>> ....
>>> Undefined simply means no one cared enough to define it.
>>
>> "undefined behavior
>> behavior, upon use of a nonportable or erroneous program construct or of
>> erroneous data, for which this document imposes no requirements" (3.4.3p1).
>>
>> Key point so pay attention to:
>> 1. It's undefined if "this document" (the C standard) imposes no
>> requirements, even if some other document does impose requirements.
>
> How does that differ to what I said?
>
It differs *from* what you said in two key ways:
1. "No one" - It still qualifies as "undefined behavior", as that term
is defined by the standard, even if someone does care enough to define
the behavior, so long as it is defined only by something other than the
standard.
Undefined behavior is often what justifies an extension to C++. The
standard requires that all strictly conforming programs be translated in
a way that conforms to the standard. If there's no way to invoke a given
extension without writing code that has undefined behavior, code that
does invoke it no longer qualifies as strictly conforming code, and an
implementation is therefore free to define the behavior of such code
behavior as implementating that extension.
2. "cares" - in many cases, the committee did care about the behavior,
but decided that the range of behaviors provided by real-world
implementations was too broad to allow the behavior to be merely
"unspecified".
Sometimes the committee says that the behavior is undefined precisely
because they do care. For instance, here's a case that's very similar to
the one under discussion:
"If a side effect on a memory location (6.7.1) is unsequenced relative
to either another side effect on the same memory location or a value
computation using the value of any object in the same memory location,
and they are not potentially concurrent (6.9.2), the behavior is
undefined." (6.9.1p10). An example is given:
i = i++ + i; // undefined behavior.
This wasn't made undefined because the committee didn't care to define
the behavior. It was made undefined because the committee cared a great
deal about such code, feeling that it was a bad idea to write such code,
and they made if undefined with the explicit purpose of discouraging the
writing of such code.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-04-03 13:02 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2bust$vaj$1@dont-email.me> |
| In reply to | #83416 |
On 02/04/2022 17:39, Muttley@dastardlyhq.com wrote: > On Sat, 2 Apr 2022 17:27:39 +0200 > David Brown <david.brown@hesbynett.no> wrote: >> On 02/04/2022 16:28, Muttley@dastardlyhq.com wrote: >>> On Sat, 2 Apr 2022 14:12:17 +0200 >>> David Brown <david.brown@hesbynett.no> wrote: >>>> It seems gcc has handled this as: >>>> >>>> ++i; >>>> ++i; >>>> a = i; >>>> b = i; >>>> >>>> and AFAIUI, this interleaving is not allowed in C++17. >>>> >>>> Prior to C++17, the code could do anything - segfault, return 42, buy >>>> you flowers - whatever it liked. >>> >>> Why would it segfault? Its simply incrementing values albeit in an >>> indeterminate order. >>> >> >> >> In C++17, the incrementing is indeterminate order. Prior to that, it is >> undefined behaviour. UB /could/ do anything. If the compiler happens > > Undefined simply means no one cared enough to define it. The compiler writers > would have to deliberately change their parameter parsing and stack pushing > code in order to crash in this instance. > That kind of argument works when code can be taken alone in small snippets, without context. But real code is rarely alone. Once things are going wrong, problems can multiply. Typically, undefined behaviour means the compiler can take short-cuts. That might mean "doing the obvious thing", but it might mean getting strange and inconsistent behaviour. Given "a = b + c;" using signed int types, the compiler is likely to generate the assembly code for a two's complement wrapping addition on most processors. But if it knows that "b" and "c" are non-negative, then it also knows that "a" is non-negative and can use that for optimisation - even if the addition overflowed and "a" contains a negative number. >> POSIX, documented compiler features, etc.), then you can't rely on it >> for any purpose. > > You can't rely on a rusty bicycle working, but its not going to shoot you in > the head. > The bike won't shoot you - but it could fall apart when you are cycling down a road, and cars swerving to miss you cause a pile-up with dozens killed. Undefined behaviour has no inherent limits to its consequences - that's why you should work to avoid it. (And no, despite some people's misunderstandings, this is not due to overly-enthusiastic optimising compilers or flaws in the language - it is fundamental to all programming, and fundamental to any kind of error or mistake in the code. Different compilers, languages, and programming styles can influence how the risks build up, but not the principles.)
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-03 04:46 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <229baf9c-b7a4-417e-81f3-1ac0351cd00cn@googlegroups.com> |
| In reply to | #83430 |
On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: > On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: > > On Sat, 2 Apr 2022 17:27:39 +0200 > > David Brown <david...@hesbynett.no> wrote: > >> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: > >>> On Sat, 2 Apr 2022 14:12:17 +0200 > >>> David Brown <david...@hesbynett.no> wrote: > >>>> It seems gcc has handled this as: > >>>> > >>>> ++i; > >>>> ++i; > >>>> a = i; > >>>> b = i; > >>>> > >>>> and AFAIUI, this interleaving is not allowed in C++17. > >>>> > >>>> Prior to C++17, the code could do anything - segfault, return 42, buy > >>>> you flowers - whatever it liked. > >>> > >>> Why would it segfault? Its simply incrementing values albeit in an > >>> indeterminate order. > >>> > >> > >> > >> In C++17, the incrementing is indeterminate order. Prior to that, it is > >> undefined behaviour. UB /could/ do anything. If the compiler happens > > > > Undefined simply means no one cared enough to define it. The compiler writers > > would have to deliberately change their parameter parsing and stack pushing > > code in order to crash in this instance. > > > That kind of argument works when code can be taken alone in small > snippets, without context. But real code is rarely alone. Once things > are going wrong, problems can multiply. > > Typically, undefined behaviour means the compiler can take short-cuts. > That might mean "doing the obvious thing", but it might mean getting > strange and inconsistent behaviour. Given "a = b + c;" using signed int > types, the compiler is likely to generate the assembly code for a two's > complement wrapping addition on most processors. But if it knows that > "b" and "c" are non-negative, then it also knows that "a" is > non-negative and can use that for optimisation - even if the addition > overflowed and "a" contains a negative number. > >> POSIX, documented compiler features, etc.), then you can't rely on it > >> for any purpose. > > > > You can't rely on a rusty bicycle working, but its not going to shoot you in > > the head. > > > The bike won't shoot you - but it could fall apart when you are cycling > down a road, and cars swerving to miss you cause a pile-up with dozens > killed. Undefined behaviour has no inherent limits to its consequences > - that's why you should work to avoid it. > > (And no, despite some people's misunderstandings, this is not due to > overly-enthusiastic optimising compilers or flaws in the language - it > is fundamental to all programming, and fundamental to any kind of error > or mistake in the code. Different compilers, languages, and programming > styles can influence how the risks build up, but not the principles.) > The central issue is that, for some programs, the worst thing you can do is terminate. For example a video game. If it crashes the game is ruined. For other programs, the worst thing you can do is return wrong results. For example a program doing statistical analysis of scientific data. If it returns wrong values, errors get into the draft paper, with potentially very far-reaching consequences. If it crashes, however, that's just a minor inconvenience. So for a video game, we want arithmetical overflow to wrap, and just hope that it causes nothing worse than a transient glitch on screen. For the analysis program, we want it to terminate with an error message.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-04-03 07:02 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <6a3be9d2-aa61-4a78-adca-b1a43bc4571bn@googlegroups.com> |
| In reply to | #83432 |
On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: > On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: > > On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: > > > On Sat, 2 Apr 2022 17:27:39 +0200 > > > David Brown <david...@hesbynett.no> wrote: > > >> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: > > >>> On Sat, 2 Apr 2022 14:12:17 +0200 > > >>> David Brown <david...@hesbynett.no> wrote: > > >>>> It seems gcc has handled this as: > > >>>> > > >>>> ++i; > > >>>> ++i; > > >>>> a = i; > > >>>> b = i; > > >>>> > > >>>> and AFAIUI, this interleaving is not allowed in C++17. > > >>>> > > >>>> Prior to C++17, the code could do anything - segfault, return 42, buy > > >>>> you flowers - whatever it liked. > > >>> > > >>> Why would it segfault? Its simply incrementing values albeit in an > > >>> indeterminate order. > > >>> > > >> > > >> > > >> In C++17, the incrementing is indeterminate order. Prior to that, it is > > >> undefined behaviour. UB /could/ do anything. If the compiler happens > > > > > > Undefined simply means no one cared enough to define it. The compiler writers > > > would have to deliberately change their parameter parsing and stack pushing > > > code in order to crash in this instance. > > > > > That kind of argument works when code can be taken alone in small > > snippets, without context. But real code is rarely alone. Once things > > are going wrong, problems can multiply. > > > > Typically, undefined behaviour means the compiler can take short-cuts. > > That might mean "doing the obvious thing", but it might mean getting > > strange and inconsistent behaviour. Given "a = b + c;" using signed int > > types, the compiler is likely to generate the assembly code for a two's > > complement wrapping addition on most processors. But if it knows that > > "b" and "c" are non-negative, then it also knows that "a" is > > non-negative and can use that for optimisation - even if the addition > > overflowed and "a" contains a negative number. > > >> POSIX, documented compiler features, etc.), then you can't rely on it > > >> for any purpose. > > > > > > You can't rely on a rusty bicycle working, but its not going to shoot you in > > > the head. > > > > > The bike won't shoot you - but it could fall apart when you are cycling > > down a road, and cars swerving to miss you cause a pile-up with dozens > > killed. Undefined behaviour has no inherent limits to its consequences > > - that's why you should work to avoid it. > > > > (And no, despite some people's misunderstandings, this is not due to > > overly-enthusiastic optimising compilers or flaws in the language - it > > is fundamental to all programming, and fundamental to any kind of error > > or mistake in the code. Different compilers, languages, and programming > > styles can influence how the risks build up, but not the principles.) > > > The central issue is that, for some programs, the worst thing you can do is > terminate. For example a video game. If it crashes the game is ruined. While the program is still in development process and so in hands of developers and testers then cheapest to track down defect is when program refuses to compile and next best is runtime crash. It does not matter if it is for entertainment or for something more serious, what matters is development cost. The theory that game is not ruined when it hangs or turns staggeringly slow, some dialog is empty, some object turns invisible or disappears, or some control does not work is questionable. It happens most commonly when development philosophy ignored what I wrote about development cost. > For other programs, the worst thing you can do is return wrong results. > For example a program doing statistical analysis of scientific data. If it > returns wrong values, errors get into the draft paper, with potentially very > far-reaching consequences. If it crashes, however, that's just a minor > inconvenience. > > So for a video game, we want arithmetical overflow to wrap, and just hope > that it causes nothing worse than a transient glitch on screen. For the > analysis program, we want it to terminate with an error message. For both we want to discover it before it reaches users. The only exception is perhaps vaporware proof of concepts meant to raise funds and never release ... that is better not to crash it during demo to potential investors.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-03 11:30 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <95132c7f-3131-4fa3-a44a-5a026777144en@googlegroups.com> |
| In reply to | #83434 |
On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: > On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: > > On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: > > > On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: > > > > On Sat, 2 Apr 2022 17:27:39 +0200 > > > > David Brown <david...@hesbynett.no> wrote: > > > >> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: > > > >>> On Sat, 2 Apr 2022 14:12:17 +0200 > > > >>> David Brown <david...@hesbynett.no> wrote: > > > >>>> It seems gcc has handled this as: > > > >>>> > > > >>>> ++i; > > > >>>> ++i; > > > >>>> a = i; > > > >>>> b = i; > > > >>>> > > > >>>> and AFAIUI, this interleaving is not allowed in C++17. > > > >>>> > > > >>>> Prior to C++17, the code could do anything - segfault, return 42, buy > > > >>>> you flowers - whatever it liked. > > > >>> > > > >>> Why would it segfault? Its simply incrementing values albeit in an > > > >>> indeterminate order. > > > >>> > > > >> > > > >> > > > >> In C++17, the incrementing is indeterminate order. Prior to that, it is > > > >> undefined behaviour. UB /could/ do anything. If the compiler happens > > > > > > > > Undefined simply means no one cared enough to define it. The compiler writers > > > > would have to deliberately change their parameter parsing and stack pushing > > > > code in order to crash in this instance. > > > > > > > That kind of argument works when code can be taken alone in small > > > snippets, without context. But real code is rarely alone. Once things > > > are going wrong, problems can multiply. > > > > > > Typically, undefined behaviour means the compiler can take short-cuts. > > > That might mean "doing the obvious thing", but it might mean getting > > > strange and inconsistent behaviour. Given "a = b + c;" using signed int > > > types, the compiler is likely to generate the assembly code for a two's > > > complement wrapping addition on most processors. But if it knows that > > > "b" and "c" are non-negative, then it also knows that "a" is > > > non-negative and can use that for optimisation - even if the addition > > > overflowed and "a" contains a negative number. > > > >> POSIX, documented compiler features, etc.), then you can't rely on it > > > >> for any purpose. > > > > > > > > You can't rely on a rusty bicycle working, but its not going to shoot you in > > > > the head. > > > > > > > The bike won't shoot you - but it could fall apart when you are cycling > > > down a road, and cars swerving to miss you cause a pile-up with dozens > > > killed. Undefined behaviour has no inherent limits to its consequences > > > - that's why you should work to avoid it. > > > > > > (And no, despite some people's misunderstandings, this is not due to > > > overly-enthusiastic optimising compilers or flaws in the language - it > > > is fundamental to all programming, and fundamental to any kind of error > > > or mistake in the code. Different compilers, languages, and programming > > > styles can influence how the risks build up, but not the principles.) > > > > > The central issue is that, for some programs, the worst thing you can do is > > terminate. For example a video game. If it crashes the game is ruined. > While the program is still in development process and so in hands of > developers and testers then cheapest to track down defect is when program > refuses to compile and next best is runtime crash. It does not matter if it is > for entertainment or for something more serious, what matters is > development cost. > If you're writing control systems for nuclear reactors, you have to have really tight quality control, including proving of algorithms. But if you're doing everyday programming, you just don't have those resources.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-04-03 21:20 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2cs1l$8t9$1@dont-email.me> |
| In reply to | #83439 |
On 03/04/2022 20:30, Malcolm McLean wrote: > On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: >> On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: >>> On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: >>>> On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: >>>>> On Sat, 2 Apr 2022 17:27:39 +0200 >>>>> David Brown <david...@hesbynett.no> wrote: >>>>>> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: >>>>>>> On Sat, 2 Apr 2022 14:12:17 +0200 >>>>>>> David Brown <david...@hesbynett.no> wrote: >>>>>>>> It seems gcc has handled this as: >>>>>>>> >>>>>>>> ++i; >>>>>>>> ++i; >>>>>>>> a = i; >>>>>>>> b = i; >>>>>>>> >>>>>>>> and AFAIUI, this interleaving is not allowed in C++17. >>>>>>>> >>>>>>>> Prior to C++17, the code could do anything - segfault, return 42, buy >>>>>>>> you flowers - whatever it liked. >>>>>>> >>>>>>> Why would it segfault? Its simply incrementing values albeit in an >>>>>>> indeterminate order. >>>>>>> >>>>>> >>>>>> >>>>>> In C++17, the incrementing is indeterminate order. Prior to that, it is >>>>>> undefined behaviour. UB /could/ do anything. If the compiler happens >>>>> >>>>> Undefined simply means no one cared enough to define it. The compiler writers >>>>> would have to deliberately change their parameter parsing and stack pushing >>>>> code in order to crash in this instance. >>>>> >>>> That kind of argument works when code can be taken alone in small >>>> snippets, without context. But real code is rarely alone. Once things >>>> are going wrong, problems can multiply. >>>> >>>> Typically, undefined behaviour means the compiler can take short-cuts. >>>> That might mean "doing the obvious thing", but it might mean getting >>>> strange and inconsistent behaviour. Given "a = b + c;" using signed int >>>> types, the compiler is likely to generate the assembly code for a two's >>>> complement wrapping addition on most processors. But if it knows that >>>> "b" and "c" are non-negative, then it also knows that "a" is >>>> non-negative and can use that for optimisation - even if the addition >>>> overflowed and "a" contains a negative number. >>>>>> POSIX, documented compiler features, etc.), then you can't rely on it >>>>>> for any purpose. >>>>> >>>>> You can't rely on a rusty bicycle working, but its not going to shoot you in >>>>> the head. >>>>> >>>> The bike won't shoot you - but it could fall apart when you are cycling >>>> down a road, and cars swerving to miss you cause a pile-up with dozens >>>> killed. Undefined behaviour has no inherent limits to its consequences >>>> - that's why you should work to avoid it. >>>> >>>> (And no, despite some people's misunderstandings, this is not due to >>>> overly-enthusiastic optimising compilers or flaws in the language - it >>>> is fundamental to all programming, and fundamental to any kind of error >>>> or mistake in the code. Different compilers, languages, and programming >>>> styles can influence how the risks build up, but not the principles.) >>>> >>> The central issue is that, for some programs, the worst thing you can do is >>> terminate. For example a video game. If it crashes the game is ruined. >> While the program is still in development process and so in hands of >> developers and testers then cheapest to track down defect is when program >> refuses to compile and next best is runtime crash. It does not matter if it is >> for entertainment or for something more serious, what matters is >> development cost. >> > If you're writing control systems for nuclear reactors, you have to have really > tight quality control, including proving of algorithms. But if you're doing > everyday programming, you just don't have those resources. > > You may not have the resources - or the ability - to write bug-free code. That does not mean you should consider some kinds of bugs "acceptable". And it certainly does not mean that you should consider some classes of undefined behaviour as "nothing to worry about, really - there's no need to be careful about integer arithmetic because there's a good chance no one will complain about the mistake". I can appreciate if you find an integer overflow bug and you mark it as low priority in your long list of bugs in the program because it just causes a visual glitch. I cannot accept the attitude that you are happy to write knowingly incorrect code and hope it causes nothing more than a visual glitch. Ultimately, these two attitudes can lead to the same thing - programs released even though you know there are bugs in them, because you don't have the time or resources to fix everything. Real life is not perfect. But there is a very big difference in the philosophies here.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-03 12:49 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <f606600a-d75b-438c-8671-0cadd35bb2d9n@googlegroups.com> |
| In reply to | #83440 |
On Sunday, 3 April 2022 at 20:20:36 UTC+1, David Brown wrote: > On 03/04/2022 20:30, Malcolm McLean wrote: > > On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: > >> On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: > >>> On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: > >>>> On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: > >>>>> On Sat, 2 Apr 2022 17:27:39 +0200 > >>>>> David Brown <david...@hesbynett.no> wrote: > >>>>>> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: > >>>>>>> On Sat, 2 Apr 2022 14:12:17 +0200 > >>>>>>> David Brown <david...@hesbynett.no> wrote: > >>>>>>>> It seems gcc has handled this as: > >>>>>>>> > >>>>>>>> ++i; > >>>>>>>> ++i; > >>>>>>>> a = i; > >>>>>>>> b = i; > >>>>>>>> > >>>>>>>> and AFAIUI, this interleaving is not allowed in C++17. > >>>>>>>> > >>>>>>>> Prior to C++17, the code could do anything - segfault, return 42, buy > >>>>>>>> you flowers - whatever it liked. > >>>>>>> > >>>>>>> Why would it segfault? Its simply incrementing values albeit in an > >>>>>>> indeterminate order. > >>>>>>> > >>>>>> > >>>>>> > >>>>>> In C++17, the incrementing is indeterminate order. Prior to that, it is > >>>>>> undefined behaviour. UB /could/ do anything. If the compiler happens > >>>>> > >>>>> Undefined simply means no one cared enough to define it. The compiler writers > >>>>> would have to deliberately change their parameter parsing and stack pushing > >>>>> code in order to crash in this instance. > >>>>> > >>>> That kind of argument works when code can be taken alone in small > >>>> snippets, without context. But real code is rarely alone. Once things > >>>> are going wrong, problems can multiply. > >>>> > >>>> Typically, undefined behaviour means the compiler can take short-cuts. > >>>> That might mean "doing the obvious thing", but it might mean getting > >>>> strange and inconsistent behaviour. Given "a = b + c;" using signed int > >>>> types, the compiler is likely to generate the assembly code for a two's > >>>> complement wrapping addition on most processors. But if it knows that > >>>> "b" and "c" are non-negative, then it also knows that "a" is > >>>> non-negative and can use that for optimisation - even if the addition > >>>> overflowed and "a" contains a negative number. > >>>>>> POSIX, documented compiler features, etc.), then you can't rely on it > >>>>>> for any purpose. > >>>>> > >>>>> You can't rely on a rusty bicycle working, but its not going to shoot you in > >>>>> the head. > >>>>> > >>>> The bike won't shoot you - but it could fall apart when you are cycling > >>>> down a road, and cars swerving to miss you cause a pile-up with dozens > >>>> killed. Undefined behaviour has no inherent limits to its consequences > >>>> - that's why you should work to avoid it. > >>>> > >>>> (And no, despite some people's misunderstandings, this is not due to > >>>> overly-enthusiastic optimising compilers or flaws in the language - it > >>>> is fundamental to all programming, and fundamental to any kind of error > >>>> or mistake in the code. Different compilers, languages, and programming > >>>> styles can influence how the risks build up, but not the principles.) > >>>> > >>> The central issue is that, for some programs, the worst thing you can do is > >>> terminate. For example a video game. If it crashes the game is ruined. > >> While the program is still in development process and so in hands of > >> developers and testers then cheapest to track down defect is when program > >> refuses to compile and next best is runtime crash. It does not matter if it is > >> for entertainment or for something more serious, what matters is > >> development cost. > >> > > If you're writing control systems for nuclear reactors, you have to have really > > tight quality control, including proving of algorithms. But if you're doing > > everyday programming, you just don't have those resources. > > > > > You may not have the resources - or the ability - to write bug-free > code. That does not mean you should consider some kinds of bugs > "acceptable". And it certainly does not mean that you should consider > some classes of undefined behaviour as "nothing to worry about, really - > there's no need to be careful about integer arithmetic because there's a > good chance no one will complain about the mistake". > > I can appreciate if you find an integer overflow bug and you mark it as > low priority in your long list of bugs in the program because it just > causes a visual glitch. > > I cannot accept the attitude that you are happy to write knowingly > incorrect code and hope it causes nothing more than a visual glitch. > > Ultimately, these two attitudes can lead to the same thing - programs > released even though you know there are bugs in them, because you don't > have the time or resources to fix everything. Real life is not perfect. > But there is a very big difference in the philosophies here. > You fail to follow. Say we have this code. FILE *fp = openfile(); int width = readinteger(fp); int height = readinteger(fp); int Npixels = width * height; // potential bug here Now of course we should put in a test before multiplying two integers from an outside source. But these sorts of errors happen. The question is that, given that despite all our best efforts this code has got through to production, how do we want the program to behave? Should we compile with the option "abort on arithmetic overflow" or "wrap on arithmetic overflow"?. As an exercise to the reader, there's a school of thought that these values should be size_t. What are the consequences of that policy for program robustness?
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <eesnimi@osa.pri.ee> |
|---|---|
| Date | 2022-04-04 00:40 +0300 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2d48q$bvt$1@dont-email.me> |
| In reply to | #83442 |
03.04.2022 22:49 Malcolm McLean kirjutas: > On Sunday, 3 April 2022 at 20:20:36 UTC+1, David Brown wrote: >> On 03/04/2022 20:30, Malcolm McLean wrote: >>> On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: >>>> On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: >>>>> On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: >>>>>> On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: >>>>>>> On Sat, 2 Apr 2022 17:27:39 +0200 >>>>>>> David Brown <david...@hesbynett.no> wrote: >>>>>>>> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: >>>>>>>>> On Sat, 2 Apr 2022 14:12:17 +0200 >>>>>>>>> David Brown <david...@hesbynett.no> wrote: >>>>>>>>>> It seems gcc has handled this as: >>>>>>>>>> >>>>>>>>>> ++i; >>>>>>>>>> ++i; >>>>>>>>>> a = i; >>>>>>>>>> b = i; >>>>>>>>>> >>>>>>>>>> and AFAIUI, this interleaving is not allowed in C++17. >>>>>>>>>> >>>>>>>>>> Prior to C++17, the code could do anything - segfault, return 42, buy >>>>>>>>>> you flowers - whatever it liked. >>>>>>>>> >>>>>>>>> Why would it segfault? Its simply incrementing values albeit in an >>>>>>>>> indeterminate order. >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> In C++17, the incrementing is indeterminate order. Prior to that, it is >>>>>>>> undefined behaviour. UB /could/ do anything. If the compiler happens >>>>>>> >>>>>>> Undefined simply means no one cared enough to define it. The compiler writers >>>>>>> would have to deliberately change their parameter parsing and stack pushing >>>>>>> code in order to crash in this instance. >>>>>>> >>>>>> That kind of argument works when code can be taken alone in small >>>>>> snippets, without context. But real code is rarely alone. Once things >>>>>> are going wrong, problems can multiply. >>>>>> >>>>>> Typically, undefined behaviour means the compiler can take short-cuts. >>>>>> That might mean "doing the obvious thing", but it might mean getting >>>>>> strange and inconsistent behaviour. Given "a = b + c;" using signed int >>>>>> types, the compiler is likely to generate the assembly code for a two's >>>>>> complement wrapping addition on most processors. But if it knows that >>>>>> "b" and "c" are non-negative, then it also knows that "a" is >>>>>> non-negative and can use that for optimisation - even if the addition >>>>>> overflowed and "a" contains a negative number. >>>>>>>> POSIX, documented compiler features, etc.), then you can't rely on it >>>>>>>> for any purpose. >>>>>>> >>>>>>> You can't rely on a rusty bicycle working, but its not going to shoot you in >>>>>>> the head. >>>>>>> >>>>>> The bike won't shoot you - but it could fall apart when you are cycling >>>>>> down a road, and cars swerving to miss you cause a pile-up with dozens >>>>>> killed. Undefined behaviour has no inherent limits to its consequences >>>>>> - that's why you should work to avoid it. >>>>>> >>>>>> (And no, despite some people's misunderstandings, this is not due to >>>>>> overly-enthusiastic optimising compilers or flaws in the language - it >>>>>> is fundamental to all programming, and fundamental to any kind of error >>>>>> or mistake in the code. Different compilers, languages, and programming >>>>>> styles can influence how the risks build up, but not the principles.) >>>>>> >>>>> The central issue is that, for some programs, the worst thing you can do is >>>>> terminate. For example a video game. If it crashes the game is ruined. >>>> While the program is still in development process and so in hands of >>>> developers and testers then cheapest to track down defect is when program >>>> refuses to compile and next best is runtime crash. It does not matter if it is >>>> for entertainment or for something more serious, what matters is >>>> development cost. >>>> >>> If you're writing control systems for nuclear reactors, you have to have really >>> tight quality control, including proving of algorithms. But if you're doing >>> everyday programming, you just don't have those resources. >>> >>> >> You may not have the resources - or the ability - to write bug-free >> code. That does not mean you should consider some kinds of bugs >> "acceptable". And it certainly does not mean that you should consider >> some classes of undefined behaviour as "nothing to worry about, really - >> there's no need to be careful about integer arithmetic because there's a >> good chance no one will complain about the mistake". >> >> I can appreciate if you find an integer overflow bug and you mark it as >> low priority in your long list of bugs in the program because it just >> causes a visual glitch. >> >> I cannot accept the attitude that you are happy to write knowingly >> incorrect code and hope it causes nothing more than a visual glitch. >> >> Ultimately, these two attitudes can lead to the same thing - programs >> released even though you know there are bugs in them, because you don't >> have the time or resources to fix everything. Real life is not perfect. >> But there is a very big difference in the philosophies here. >> > You fail to follow. > Say we have this code. > > FILE *fp = openfile(); > int width = readinteger(fp); > int height = readinteger(fp); Hoping both openfile() and readinteger() functions check for errors internally and throw relevant exceptions. > int Npixels = width * height; // potential bug here > > Now of course we should put in a test before multiplying two integers > from an outside source. But these sorts of errors happen. The question is > that, given that despite all our best efforts this code has got through to > production, how do we want the program to behave? If a bug has slipped through into production, we want to minimize the cost of dealing with the bug. These costs will depend on a myriad of factors, like how likely the program would still function correctly even if the bug is hit, how many customers are affected, how costly is the QA cycle for releasing a patch version, how costly is losing some customers because of the bug, etc. There is no single answer. For the customer it does not really matter if they cannot use our program because we had put too many assertions/aborts in it, or because there are show-stopper bugs in it. > Should we compile with the option "abort on arithmetic overflow" or > "wrap on arithmetic overflow"?. That will also depend on other considerations, like how much performance is lost for detecting the arithmetic overflow, and how devastating it would be to have an incorrect result instead of a program abort, or vice versa. > > As an exercise to the reader, there's a school of thought that these values > should be size_t. What are the consequences of that policy for program > robustness? Widths, heights, and lengths are not periodic variables like e.g. angles, so it would be counter-productive to try to encode them via periodic types like unsigned integrals in C++. For starters, the overflows would become defined behavior with unsigned types, meaning that one cannot trap them, or even tell apart bugs and features. So here, clearly a signed integer type should be preferred. The exact preferred signed integer type for scalar variables should match the hardware word, nowadays this is int64.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-03 15:40 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <3d7bfd9f-c003-46eb-a82a-cd66ba483eaan@googlegroups.com> |
| In reply to | #83443 |
On Sunday, 3 April 2022 at 22:40:57 UTC+1, Paavo Helde wrote: > 03.04.2022 22:49 Malcolm McLean kirjutas: > > On Sunday, 3 April 2022 at 20:20:36 UTC+1, David Brown wrote: > >> On 03/04/2022 20:30, Malcolm McLean wrote: > >>> On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: > >>>> On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: > >>>>> On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: > >>>>>> On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: > >>>>>>> On Sat, 2 Apr 2022 17:27:39 +0200 > >>>>>>> David Brown <david...@hesbynett.no> wrote: > >>>>>>>> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: > >>>>>>>>> On Sat, 2 Apr 2022 14:12:17 +0200 > >>>>>>>>> David Brown <david...@hesbynett.no> wrote: > >>>>>>>>>> It seems gcc has handled this as: > >>>>>>>>>> > >>>>>>>>>> ++i; > >>>>>>>>>> ++i; > >>>>>>>>>> a = i; > >>>>>>>>>> b = i; > >>>>>>>>>> > >>>>>>>>>> and AFAIUI, this interleaving is not allowed in C++17. > >>>>>>>>>> > >>>>>>>>>> Prior to C++17, the code could do anything - segfault, return 42, buy > >>>>>>>>>> you flowers - whatever it liked. > >>>>>>>>> > >>>>>>>>> Why would it segfault? Its simply incrementing values albeit in an > >>>>>>>>> indeterminate order. > >>>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> In C++17, the incrementing is indeterminate order. Prior to that, it is > >>>>>>>> undefined behaviour. UB /could/ do anything. If the compiler happens > >>>>>>> > >>>>>>> Undefined simply means no one cared enough to define it. The compiler writers > >>>>>>> would have to deliberately change their parameter parsing and stack pushing > >>>>>>> code in order to crash in this instance. > >>>>>>> > >>>>>> That kind of argument works when code can be taken alone in small > >>>>>> snippets, without context. But real code is rarely alone. Once things > >>>>>> are going wrong, problems can multiply. > >>>>>> > >>>>>> Typically, undefined behaviour means the compiler can take short-cuts. > >>>>>> That might mean "doing the obvious thing", but it might mean getting > >>>>>> strange and inconsistent behaviour. Given "a = b + c;" using signed int > >>>>>> types, the compiler is likely to generate the assembly code for a two's > >>>>>> complement wrapping addition on most processors. But if it knows that > >>>>>> "b" and "c" are non-negative, then it also knows that "a" is > >>>>>> non-negative and can use that for optimisation - even if the addition > >>>>>> overflowed and "a" contains a negative number. > >>>>>>>> POSIX, documented compiler features, etc.), then you can't rely on it > >>>>>>>> for any purpose. > >>>>>>> > >>>>>>> You can't rely on a rusty bicycle working, but its not going to shoot you in > >>>>>>> the head. > >>>>>>> > >>>>>> The bike won't shoot you - but it could fall apart when you are cycling > >>>>>> down a road, and cars swerving to miss you cause a pile-up with dozens > >>>>>> killed. Undefined behaviour has no inherent limits to its consequences > >>>>>> - that's why you should work to avoid it. > >>>>>> > >>>>>> (And no, despite some people's misunderstandings, this is not due to > >>>>>> overly-enthusiastic optimising compilers or flaws in the language - it > >>>>>> is fundamental to all programming, and fundamental to any kind of error > >>>>>> or mistake in the code. Different compilers, languages, and programming > >>>>>> styles can influence how the risks build up, but not the principles.) > >>>>>> > >>>>> The central issue is that, for some programs, the worst thing you can do is > >>>>> terminate. For example a video game. If it crashes the game is ruined. > >>>> While the program is still in development process and so in hands of > >>>> developers and testers then cheapest to track down defect is when program > >>>> refuses to compile and next best is runtime crash. It does not matter if it is > >>>> for entertainment or for something more serious, what matters is > >>>> development cost. > >>>> > >>> If you're writing control systems for nuclear reactors, you have to have really > >>> tight quality control, including proving of algorithms. But if you're doing > >>> everyday programming, you just don't have those resources. > >>> > >>> > >> You may not have the resources - or the ability - to write bug-free > >> code. That does not mean you should consider some kinds of bugs > >> "acceptable". And it certainly does not mean that you should consider > >> some classes of undefined behaviour as "nothing to worry about, really - > >> there's no need to be careful about integer arithmetic because there's a > >> good chance no one will complain about the mistake". > >> > >> I can appreciate if you find an integer overflow bug and you mark it as > >> low priority in your long list of bugs in the program because it just > >> causes a visual glitch. > >> > >> I cannot accept the attitude that you are happy to write knowingly > >> incorrect code and hope it causes nothing more than a visual glitch. > >> > >> Ultimately, these two attitudes can lead to the same thing - programs > >> released even though you know there are bugs in them, because you don't > >> have the time or resources to fix everything. Real life is not perfect. > >> But there is a very big difference in the philosophies here. > >> > > You fail to follow. > > Say we have this code. > > > > FILE *fp = openfile(); > > int width = readinteger(fp); > > int height = readinteger(fp); > Hoping both openfile() and readinteger() functions check for errors > internally and throw relevant exceptions. > > int Npixels = width * height; // potential bug here > > > > Now of course we should put in a test before multiplying two integers > > from an outside source. But these sorts of errors happen. The question is > > that, given that despite all our best efforts this code has got through to > > production, how do we want the program to behave? > If a bug has slipped through into production, we want to minimize the > cost of dealing with the bug. These costs will depend on a myriad of > factors, like how likely the program would still function correctly even > if the bug is hit, how many customers are affected, how costly is the QA > cycle for releasing a patch version, how costly is losing some customers > because of the bug, etc. There is no single answer. For the customer it > does not really matter if they cannot use our program because we had put > too many assertions/aborts in it, or because there are show-stopper bugs > in it. > That can be a consideration. Not the immediate cost of the bug to the user, but the cost of dealing with the bug reports. Unless the software really is critical, so that any error whatsoever requires immediate discontinuation of the software, a bug that ships is unlikely to make the software unusable. Testers are rarely that incompetent. In this case, what would happen is that an integer overflow would occur when fed a malformed file with huge dimensions. The user could still use the software as long as he only loaded well-formed files. As you say, there can be no single answer. In general, however, it's better to terminate with an error message. That's no different to the computer losing power. Producing wrong results, on the other hand, can have far-reaching consequences. But there are exceptions, like video games.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-04-04 09:13 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2e5qm$dde$1@dont-email.me> |
| In reply to | #83444 |
On 04/04/2022 00:40, Malcolm McLean wrote: > As you say, there can be no single answer. True. > In general, however, it's better to > terminate with an error message. Wrong. There is no "in general". > That's no different to the computer losing > power. Wrong. > Producing wrong results, on the other hand, can have far-reaching > consequences. Correct. > But there are exceptions, like video games. Wrong. Incorrect results in video games can most certainly have far-reaching consequences. Use your imagination a bit. In some types of code, it is possible to track, contain or limit certain types of errors, accept that these can occur, and control the consequences. This is especially true of run-time errors (like failure to access a file), rather than software bugs. But it can even apply to software bugs too - typically using managed virtual machines or other constrained environments to run the code. There is also some code for which particular types of wrong answer are not a big problem. It depends on what you are doing with the results, and what happens afterwards. If you have a function that does some calculations and prints the results which is then interpreted by a human, it is not unlikely that an incorrect result will be inconsequential. Overflows in the calculation might then not be serious a problem. But if those results are used for other purposes, they most certainly could be.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-04-04 09:02 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2e55d$920$1@dont-email.me> |
| In reply to | #83442 |
On 03/04/2022 21:49, Malcolm McLean wrote: > On Sunday, 3 April 2022 at 20:20:36 UTC+1, David Brown wrote: >> On 03/04/2022 20:30, Malcolm McLean wrote: >>> On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: >>>> On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: >>>>> On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: >>>>>> On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: >>>>>>> On Sat, 2 Apr 2022 17:27:39 +0200 >>>>>>> David Brown <david...@hesbynett.no> wrote: >>>>>>>> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: >>>>>>>>> On Sat, 2 Apr 2022 14:12:17 +0200 >>>>>>>>> David Brown <david...@hesbynett.no> wrote: >>>>>>>>>> It seems gcc has handled this as: >>>>>>>>>> >>>>>>>>>> ++i; >>>>>>>>>> ++i; >>>>>>>>>> a = i; >>>>>>>>>> b = i; >>>>>>>>>> >>>>>>>>>> and AFAIUI, this interleaving is not allowed in C++17. >>>>>>>>>> >>>>>>>>>> Prior to C++17, the code could do anything - segfault, return 42, buy >>>>>>>>>> you flowers - whatever it liked. >>>>>>>>> >>>>>>>>> Why would it segfault? Its simply incrementing values albeit in an >>>>>>>>> indeterminate order. >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> In C++17, the incrementing is indeterminate order. Prior to that, it is >>>>>>>> undefined behaviour. UB /could/ do anything. If the compiler happens >>>>>>> >>>>>>> Undefined simply means no one cared enough to define it. The compiler writers >>>>>>> would have to deliberately change their parameter parsing and stack pushing >>>>>>> code in order to crash in this instance. >>>>>>> >>>>>> That kind of argument works when code can be taken alone in small >>>>>> snippets, without context. But real code is rarely alone. Once things >>>>>> are going wrong, problems can multiply. >>>>>> >>>>>> Typically, undefined behaviour means the compiler can take short-cuts. >>>>>> That might mean "doing the obvious thing", but it might mean getting >>>>>> strange and inconsistent behaviour. Given "a = b + c;" using signed int >>>>>> types, the compiler is likely to generate the assembly code for a two's >>>>>> complement wrapping addition on most processors. But if it knows that >>>>>> "b" and "c" are non-negative, then it also knows that "a" is >>>>>> non-negative and can use that for optimisation - even if the addition >>>>>> overflowed and "a" contains a negative number. >>>>>>>> POSIX, documented compiler features, etc.), then you can't rely on it >>>>>>>> for any purpose. >>>>>>> >>>>>>> You can't rely on a rusty bicycle working, but its not going to shoot you in >>>>>>> the head. >>>>>>> >>>>>> The bike won't shoot you - but it could fall apart when you are cycling >>>>>> down a road, and cars swerving to miss you cause a pile-up with dozens >>>>>> killed. Undefined behaviour has no inherent limits to its consequences >>>>>> - that's why you should work to avoid it. >>>>>> >>>>>> (And no, despite some people's misunderstandings, this is not due to >>>>>> overly-enthusiastic optimising compilers or flaws in the language - it >>>>>> is fundamental to all programming, and fundamental to any kind of error >>>>>> or mistake in the code. Different compilers, languages, and programming >>>>>> styles can influence how the risks build up, but not the principles.) >>>>>> >>>>> The central issue is that, for some programs, the worst thing you can do is >>>>> terminate. For example a video game. If it crashes the game is ruined. >>>> While the program is still in development process and so in hands of >>>> developers and testers then cheapest to track down defect is when program >>>> refuses to compile and next best is runtime crash. It does not matter if it is >>>> for entertainment or for something more serious, what matters is >>>> development cost. >>>> >>> If you're writing control systems for nuclear reactors, you have to have really >>> tight quality control, including proving of algorithms. But if you're doing >>> everyday programming, you just don't have those resources. >>> >>> >> You may not have the resources - or the ability - to write bug-free >> code. That does not mean you should consider some kinds of bugs >> "acceptable". And it certainly does not mean that you should consider >> some classes of undefined behaviour as "nothing to worry about, really - >> there's no need to be careful about integer arithmetic because there's a >> good chance no one will complain about the mistake". >> >> I can appreciate if you find an integer overflow bug and you mark it as >> low priority in your long list of bugs in the program because it just >> causes a visual glitch. >> >> I cannot accept the attitude that you are happy to write knowingly >> incorrect code and hope it causes nothing more than a visual glitch. >> >> Ultimately, these two attitudes can lead to the same thing - programs >> released even though you know there are bugs in them, because you don't >> have the time or resources to fix everything. Real life is not perfect. >> But there is a very big difference in the philosophies here. >> > You fail to follow. > Say we have this code. > > FILE *fp = openfile(); > int width = readinteger(fp); > int height = readinteger(fp); > int Npixels = width * height; // potential bug here > > Now of course we should put in a test before multiplying two integers > from an outside source. But these sorts of errors happen. The question is > that, given that despite all our best efforts this code has got through to > production, how do we want the program to behave? > > Should we compile with the option "abort on arithmetic overflow" or > "wrap on arithmetic overflow"?. Obviously you don't want "wrap on arithmetic overflow", because a negative size would be absurd and could lead to all sorts of problems. And in a game you probably don't want to enable a compiler feature that can produce slower code. (Few compilers even support "wrap on overflow" - gcc and clang with "-fwrapv" are the only ones I know.) During development and testing, you might want "abort on arithmetic overflow" to find the flaws. Beyond that, it depends on whether the file in question is considered part of the program or not. If it is part of the program, you can trust it - and thus you want "undefined behaviour on overflow" or you'd really have to check /everything/ in the file. If it is not part of the program, it is outside information and must be sanitized before use. And then "undefined behaviour on overflow" is fine. > > As an exercise to the reader, there's a school of thought that these values > should be size_t. What are the consequences of that policy for program > robustness? It is just as bad.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-04 02:07 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <567bd57a-021d-469b-a12b-d4c1371b97d3n@googlegroups.com> |
| In reply to | #83447 |
On Monday, 4 April 2022 at 08:02:21 UTC+1, David Brown wrote: > On 03/04/2022 21:49, Malcolm McLean wrote: > > On Sunday, 3 April 2022 at 20:20:36 UTC+1, David Brown wrote: > >> On 03/04/2022 20:30, Malcolm McLean wrote: > >>> On Sunday, 3 April 2022 at 15:02:19 UTC+1, Öö Tiib wrote: > >>>> On Sunday, 3 April 2022 at 14:47:06 UTC+3, Malcolm McLean wrote: > >>>>> On Sunday, 3 April 2022 at 12:03:08 UTC+1, David Brown wrote: > >>>>>> On 02/04/2022 17:39, Mut...@dastardlyhq.com wrote: > >>>>>>> On Sat, 2 Apr 2022 17:27:39 +0200 > >>>>>>> David Brown <david...@hesbynett.no> wrote: > >>>>>>>> On 02/04/2022 16:28, Mut...@dastardlyhq.com wrote: > >>>>>>>>> On Sat, 2 Apr 2022 14:12:17 +0200 > >>>>>>>>> David Brown <david...@hesbynett.no> wrote: > >>>>>>>>>> It seems gcc has handled this as: > >>>>>>>>>> > >>>>>>>>>> ++i; > >>>>>>>>>> ++i; > >>>>>>>>>> a = i; > >>>>>>>>>> b = i; > >>>>>>>>>> > >>>>>>>>>> and AFAIUI, this interleaving is not allowed in C++17. > >>>>>>>>>> > >>>>>>>>>> Prior to C++17, the code could do anything - segfault, return 42, buy > >>>>>>>>>> you flowers - whatever it liked. > >>>>>>>>> > >>>>>>>>> Why would it segfault? Its simply incrementing values albeit in an > >>>>>>>>> indeterminate order. > >>>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> In C++17, the incrementing is indeterminate order. Prior to that, it is > >>>>>>>> undefined behaviour. UB /could/ do anything. If the compiler happens > >>>>>>> > >>>>>>> Undefined simply means no one cared enough to define it. The compiler writers > >>>>>>> would have to deliberately change their parameter parsing and stack pushing > >>>>>>> code in order to crash in this instance. > >>>>>>> > >>>>>> That kind of argument works when code can be taken alone in small > >>>>>> snippets, without context. But real code is rarely alone. Once things > >>>>>> are going wrong, problems can multiply. > >>>>>> > >>>>>> Typically, undefined behaviour means the compiler can take short-cuts. > >>>>>> That might mean "doing the obvious thing", but it might mean getting > >>>>>> strange and inconsistent behaviour. Given "a = b + c;" using signed int > >>>>>> types, the compiler is likely to generate the assembly code for a two's > >>>>>> complement wrapping addition on most processors. But if it knows that > >>>>>> "b" and "c" are non-negative, then it also knows that "a" is > >>>>>> non-negative and can use that for optimisation - even if the addition > >>>>>> overflowed and "a" contains a negative number. > >>>>>>>> POSIX, documented compiler features, etc.), then you can't rely on it > >>>>>>>> for any purpose. > >>>>>>> > >>>>>>> You can't rely on a rusty bicycle working, but its not going to shoot you in > >>>>>>> the head. > >>>>>>> > >>>>>> The bike won't shoot you - but it could fall apart when you are cycling > >>>>>> down a road, and cars swerving to miss you cause a pile-up with dozens > >>>>>> killed. Undefined behaviour has no inherent limits to its consequences > >>>>>> - that's why you should work to avoid it. > >>>>>> > >>>>>> (And no, despite some people's misunderstandings, this is not due to > >>>>>> overly-enthusiastic optimising compilers or flaws in the language - it > >>>>>> is fundamental to all programming, and fundamental to any kind of error > >>>>>> or mistake in the code. Different compilers, languages, and programming > >>>>>> styles can influence how the risks build up, but not the principles.) > >>>>>> > >>>>> The central issue is that, for some programs, the worst thing you can do is > >>>>> terminate. For example a video game. If it crashes the game is ruined. > >>>> While the program is still in development process and so in hands of > >>>> developers and testers then cheapest to track down defect is when program > >>>> refuses to compile and next best is runtime crash. It does not matter if it is > >>>> for entertainment or for something more serious, what matters is > >>>> development cost. > >>>> > >>> If you're writing control systems for nuclear reactors, you have to have really > >>> tight quality control, including proving of algorithms. But if you're doing > >>> everyday programming, you just don't have those resources. > >>> > >>> > >> You may not have the resources - or the ability - to write bug-free > >> code. That does not mean you should consider some kinds of bugs > >> "acceptable". And it certainly does not mean that you should consider > >> some classes of undefined behaviour as "nothing to worry about, really - > >> there's no need to be careful about integer arithmetic because there's a > >> good chance no one will complain about the mistake". > >> > >> I can appreciate if you find an integer overflow bug and you mark it as > >> low priority in your long list of bugs in the program because it just > >> causes a visual glitch. > >> > >> I cannot accept the attitude that you are happy to write knowingly > >> incorrect code and hope it causes nothing more than a visual glitch. > >> > >> Ultimately, these two attitudes can lead to the same thing - programs > >> released even though you know there are bugs in them, because you don't > >> have the time or resources to fix everything. Real life is not perfect. > >> But there is a very big difference in the philosophies here. > >> > > You fail to follow. > > Say we have this code. > > > > FILE *fp = openfile(); > > int width = readinteger(fp); > > int height = readinteger(fp); > > int Npixels = width * height; // potential bug here > > > > Now of course we should put in a test before multiplying two integers > > from an outside source. But these sorts of errors happen. The question is > > that, given that despite all our best efforts this code has got through to > > production, how do we want the program to behave? > > > > Should we compile with the option "abort on arithmetic overflow" or > > "wrap on arithmetic overflow"?. > Obviously you don't want "wrap on arithmetic overflow", because a > negative size would be absurd and could lead to all sorts of problems. > And in a game you probably don't want to enable a compiler feature that > can produce slower code. (Few compilers even support "wrap on overflow" > - gcc and clang with "-fwrapv" are the only ones I know.) > Generally the processors primitive operations will wrap two's complement arithmetic. So to raise a signal on overflow is more expensive rather than less expensive. > > During development and testing, you might want "abort on arithmetic > overflow" to find the flaws. It's hard to think of situation where you want wrapping during debug. Release is a different matter. > > Beyond that, it depends on whether the file in question is considered > part of the program or not. If it is part of the program, you can trust > it - and thus you want "undefined behaviour on overflow" or you'd really > have to check /everything/ in the file. If it is not part of the > program, it is outside information and must be sanitized before use. > And then "undefined behaviour on overflow" is fine. > Before we can write x = a * b, with signed integer types, we need to know that the product will fit in x. That's very burdensome, and most of the time we know that a and b must be small. If a and b are read in from a user-supplied file, the we don't know that, of course. > > > As an exercise to the reader, there's a school of thought that these values > > should be size_t. What are the consequences of that policy for program > > robustness? > It is just as bad. > It's impossible to tell the program to raise the signal on overflow, because in this case overflow is defined by the standard. it's not the case that defined behaviour is automatically better than undefined behaviour. Often an undefined behaviour bug can be easier to mitigate (the program crashes on load of a corrupt file with the message "integer overflow" rather than opening up a security bug that allows a specially-crafted exploit image to execute arbitrary machine code).
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-04-04 13:28 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2ekpd$qpk$1@dont-email.me> |
| In reply to | #83453 |
On 04/04/2022 11:07, Malcolm McLean wrote: > On Monday, 4 April 2022 at 08:02:21 UTC+1, David Brown wrote: >> On 03/04/2022 21:49, Malcolm McLean wrote: >>> On Sunday, 3 April 2022 at 20:20:36 UTC+1, David Brown wrote: >>>> On 03/04/2022 20:30, Malcolm McLean wrote: <snip> >>>>> If you're writing control systems for nuclear reactors, you have to have really >>>>> tight quality control, including proving of algorithms. But if you're doing >>>>> everyday programming, you just don't have those resources. >>>>> >>>>> >>>> You may not have the resources - or the ability - to write bug-free >>>> code. That does not mean you should consider some kinds of bugs >>>> "acceptable". And it certainly does not mean that you should consider >>>> some classes of undefined behaviour as "nothing to worry about, really - >>>> there's no need to be careful about integer arithmetic because there's a >>>> good chance no one will complain about the mistake". >>>> >>>> I can appreciate if you find an integer overflow bug and you mark it as >>>> low priority in your long list of bugs in the program because it just >>>> causes a visual glitch. >>>> >>>> I cannot accept the attitude that you are happy to write knowingly >>>> incorrect code and hope it causes nothing more than a visual glitch. >>>> >>>> Ultimately, these two attitudes can lead to the same thing - programs >>>> released even though you know there are bugs in them, because you don't >>>> have the time or resources to fix everything. Real life is not perfect. >>>> But there is a very big difference in the philosophies here. >>>> >>> You fail to follow. >>> Say we have this code. >>> >>> FILE *fp = openfile(); >>> int width = readinteger(fp); >>> int height = readinteger(fp); >>> int Npixels = width * height; // potential bug here >>> >>> Now of course we should put in a test before multiplying two integers >>> from an outside source. But these sorts of errors happen. The question is >>> that, given that despite all our best efforts this code has got through to >>> production, how do we want the program to behave? >>> >>> Should we compile with the option "abort on arithmetic overflow" or >>> "wrap on arithmetic overflow"?. >> Obviously you don't want "wrap on arithmetic overflow", because a >> negative size would be absurd and could lead to all sorts of problems. >> And in a game you probably don't want to enable a compiler feature that >> can produce slower code. (Few compilers even support "wrap on overflow" >> - gcc and clang with "-fwrapv" are the only ones I know.) >> > Generally the processors primitive operations will wrap two's complement > arithmetic. So to raise a signal on overflow is more expensive rather > than less expensive. "Generally" means "not always". For the very simple case of adding two numbers, wrapping is typically as efficient as UB on overflow. (Remember that wrapping is a perfectly acceptable "implementation" of UB.) Once you start including comparisons, or mixing types of different sizes, it is not always as simple. >> >> During development and testing, you might want "abort on arithmetic >> overflow" to find the flaws. It's hard to think of situation where you want wrapping during debug. > Release is a different matter. >> >> Beyond that, it depends on whether the file in question is considered >> part of the program or not. If it is part of the program, you can trust >> it - and thus you want "undefined behaviour on overflow" or you'd really >> have to check /everything/ in the file. If it is not part of the >> program, it is outside information and must be sanitized before use. >> And then "undefined behaviour on overflow" is fine. >> > Before we can write x = a * b, with signed integer types, we need to know > that the product will fit in x. You also need that for unsigned types, if you are looking for a result that matches normal multiplication rather than modulo operations. (Just because arithmetic is fully defined for unsigned types, does not mean your results are always correct.) > That's very burdensome, and most of the time > we know that a and b must be small. If a and b are read in from a user-supplied > file, the we don't know that, of course. Then don't multiply them until you /do/ know. Or make sure the user is aware that this is all "garbage in, garbage out" and it is their responsibility to provide valid data in the files and that your program makes no guarantees of correct or safe behaviour given invalid data. >> >>> As an exercise to the reader, there's a school of thought that these values >>> should be size_t. What are the consequences of that policy for program >>> robustness? >> It is just as bad. >> > It's impossible to tell the program to raise the signal on overflow, because > in this case overflow is defined by the standard. I mean using size_t as an arithmetic type, without care or consideration for the values, is just as bad as using "int". The fact that the arithmetic is defined behaviour does not guarantee you correct results (depending on what you view as "correct"). In terms of getting the mathematically (assuming you don't actually want modulo wrapping) correct results from calculations, unsigned types are just as bad as signed types. > it's not the case that > defined behaviour is automatically better than undefined behaviour. > Often an undefined behaviour bug can be easier to mitigate (the program > crashes on load of a corrupt file with the message "integer overflow" > rather than opening up a security bug that allows a specially-crafted > exploit image to execute arbitrary machine code). Bugs are bugs. Once you have executed buggy code, all bets are off. There are no inherent limitations to the results - no guarantees that the effects will be minor "glitches", no guarantees that it will not be a security problem, and no guarantees that you'll get a crash or error message. It can be good to write code in a way that allows certain classes of bugs to be turned into defined behaviour that guarantees an error message - "sanitizers" are useful development tools. But it is even better if you can find development processes that reduce the risk of bugs being written into the code, or increase their likelihood of being spotted early in the process. Start by eliminating the idea that you can be lazy about some mistakes because they just cause visual glitches. Leave "advanced" stuff like choice of integer types until you have first understood the importance of writing correct code.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2022-04-04 06:01 -0700 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <36efdae0-f340-4958-b082-bd4932e87e15n@googlegroups.com> |
| In reply to | #83458 |
On Monday, 4 April 2022 at 12:29:00 UTC+1, David Brown wrote: > On 04/04/2022 11:07, Malcolm McLean wrote: > > > Generally the processors primitive operations will wrap two's complement > > arithmetic. So to raise a signal on overflow is more expensive rather > > than less expensive. > "Generally" means "not always". For the very simple case of adding two > numbers, wrapping is typically as efficient as UB on overflow. > (Remember that wrapping is a perfectly acceptable "implementation" of > UB.) Once you start including comparisons, or mixing types of different > sizes, it is not always as simple. > If you wrap, you do not raise a signal. Generally this is cheaper than raising a signal because wrapping requires less circuitry than detecting overflow and raising a signal. You've got it the wrong way round. Now if I was arrongant and patronising like you, I'd say something arrrogant and patronising at this point. > > > Before we can write x = a * b, with signed integer types, we need to know > > that the product will fit in x. > You also need that for unsigned types, if you are looking for a result > that matches normal multiplication rather than modulo operations. (Just > because arithmetic is fully defined for unsigned types, does not mean > your results are always correct.) You're repeating my points back to me, without realising that you are doing so. I've alreeady made the point that unsigned overflow is often worse. Because it is defined behaviour. You cannot get an exception. > > That's very burdensome, and most of the time > > we know that a and b must be small. If a and b are read in from a user-supplied > > file, the we don't know that, of course. > Then don't multiply them until you /do/ know. > > Or make sure the user is aware that this is all "garbage in, garbage > out" and it is their responsibility to provide valid data in the files > and that your program makes no guarantees of correct or safe behaviour > given invalid data. > That's a possibility. In fact you normally say that the software offers no guarantees of correct or safe behaviour undeer any circumstances. Liability is limited to the amount of money the customer paid for the software. You have no commeercial experience, obviously. > > It can be good to write code in a way that allows certain classes of > bugs to be turned into defined behaviour that guarantees an error > message - "sanitizers" are useful development tools. But it is even > better if you can find development processes that reduce the risk of > bugs being written into the code, or increase their likelihood of being > spotted early in the process. > And it can be good to turn the undefined behaviour (by C++) of integer overflow into the defined behaviour (by the compiler) of raising an exception. Then bugs are less likely to be serious. You show no ability to understand this point. > > Start by eliminating the idea that you can be lazy about some mistakes > because they just cause visual glitches. Leave "advanced" stuff like > choice of integer types until you have first understood the importance > of writing correct code. > Noow this really takes thee biscuit.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2022-04-04 19:11 +0200 |
| Subject | Re: GCC hasn't even gotten around to sequencing argument evaluation |
| Message-ID | <t2f8sl$62t$1@dont-email.me> |
| In reply to | #83461 |
On 04/04/2022 15:01, Malcolm McLean wrote: > On Monday, 4 April 2022 at 12:29:00 UTC+1, David Brown wrote: >> On 04/04/2022 11:07, Malcolm McLean wrote: >> >>> Generally the processors primitive operations will wrap two's complement >>> arithmetic. So to raise a signal on overflow is more expensive rather >>> than less expensive. >> "Generally" means "not always". For the very simple case of adding two >> numbers, wrapping is typically as efficient as UB on overflow. >> (Remember that wrapping is a perfectly acceptable "implementation" of >> UB.) Once you start including comparisons, or mixing types of different >> sizes, it is not always as simple. >> > If you wrap, you do not raise a signal. Generally this is cheaper than raising > a signal because wrapping requires less circuitry than detecting overflow > and raising a signal. You've got it the wrong way round. Now if I was > arrongant and patronising like you, I'd say something arrrogant and > patronising at this point. I don't think I am being "arrogant and patronising" - I am saying I think you are showing a poor attitude to the importance of correct code, are mistaken in what you consider to be possible consequences of certain types of mistakes, and wrong about what might or might not be more efficient in code generation. Would it be "patronising" to point out that I said "Once you start including comparisons, or mixing types of different sizes, it is not always as simple", so discussions of the circuits used for an addition are irrelevant? Would it be "arrogant" to note that addition circuits on most processors /always/ include overflow detection - because sometimes these flags /are/ used, and it is cheaper in the circuitry to generate that signal internally for every addition than to generate it only sometimes? (It would certainly be off-topic to do so, because implementation circuitry is not relevant here.) I don't intend to be either arrogant or patronising, but I do disagree with some of your points and comments (while also agreeing with others). >> >>> Before we can write x = a * b, with signed integer types, we need to know >>> that the product will fit in x. >> You also need that for unsigned types, if you are looking for a result >> that matches normal multiplication rather than modulo operations. (Just >> because arithmetic is fully defined for unsigned types, does not mean >> your results are always correct.) > > You're repeating my points back to me, without realising that you are doing so. > I've alreeady made the point that unsigned overflow is often worse. Because > it is defined behaviour. You cannot get an exception. It is not worse - it is much the same, in regard to the code itself. You do not get an exception for unsigned overflow in C (or C++). You do not get an exception for signed overflow in C (or C++). In C (and C++), it is the duty of the programmer to ensure that there will not be overflows in signed arithmetic, /before/ doing the calculation. How you do that, is up to you - there is no single "best" method. If you want your unsigned arithmetic to have the same results as for normal mathematical integer arithmetic, rather than modulo arithmetic, then you also need to ensure there is no overflow (or that the final results are correct regardless of the overflow). You can, if you want, do this by determining the overflow /after/ the operation when dealing with unsigned operations. I'm sure you know all this, but I don't think you are expressing it well. I'm sure you also know that "exception" is a term with a specific meaning in C++, and that you do not get an exception for signed overflow or unsigned overflow. What you /can/ get, if you use appropriate tools and flags or options, is debugging and testing help to cause some kind of debug output to be produced for at least some cases of signed overflow. And you /cannot/ get that for unsigned overflow - as you say, this is because it has defined behaviour. This is an advantage C and C++ have over, say, Java, precisely because they have explicit undefined behaviour here. >>> That's very burdensome, and most of the time >>> we know that a and b must be small. If a and b are read in from a user-supplied >>> file, the we don't know that, of course. >> Then don't multiply them until you /do/ know. >> >> Or make sure the user is aware that this is all "garbage in, garbage >> out" and it is their responsibility to provide valid data in the files >> and that your program makes no guarantees of correct or safe behaviour >> given invalid data. >> > That's a possibility. In fact you normally say that the software offers no > guarantees of correct or safe behaviour undeer any circumstances. > Liability is limited to the amount of money the customer paid for the > software. You have no commeercial experience, obviously. I /do/ have commercial experience. I also have experience making software where quality and correctness /is/ guaranteed, and where reliable safe behaviour is a requirement. I have plenty of experience writing code that will only work if the inputs are valid, and nothing is even specified as to what might happen if they are invalid. What I do /not/ have experience in doing, is writing software where it is acceptable to say "this data is not under our control, but we'll assume it's safe" or "I know this code might be wrong but I can't be bothered doing it correctly - probably no one will notice any mistakes". >> >> It can be good to write code in a way that allows certain classes of >> bugs to be turned into defined behaviour that guarantees an error >> message - "sanitizers" are useful development tools. But it is even >> better if you can find development processes that reduce the risk of >> bugs being written into the code, or increase their likelihood of being >> spotted early in the process. >> > And it can be good to turn the undefined behaviour (by C++) of > integer overflow into the defined behaviour (by the compiler) of > raising an exception. Then bugs are less likely to be serious. You > show no ability to understand this point. That suggestion was not discussed (outside of its use for development and debugging, where I explicitly recommended it), so I have given no impression as to whether or not I might understand its benefit in released code. I /do/ understand it, and I agree that in some circumstances it can make sense to have checks enabled even after release. I would rather handle this using appropriate C++ classes than enabling it for /all/ integer arithmetic, since that would be hugely inefficient. (And if you want fully checked code and don't mind a performance hit, there are other languages that might be better choices than C++.) Such classes would also let me raise C++ exceptions, rather than whatever /you/ mean be "exception" here (I think you mean a signal or trap). >> >> Start by eliminating the idea that you can be lazy about some mistakes >> because they just cause visual glitches. Leave "advanced" stuff like >> choice of integer types until you have first understood the importance >> of writing correct code. >> > Noow this really takes thee biscuit. > Okay, I have to admit that /was/ patronising. But I simply do not accept your premise that it's fine to leave certain code full of potential bugs just because you don't think the consequences are major.
[toc] | [prev] | [next] | [standalone]
Page 4 of 7 — ← Prev page 1 2 3 [4] 5 6 7 Next page →
Back to top | Article view | comp.lang.c++
csiph-web