Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #89514 > unrolled thread
| Started by | Lynn McGuire <lynnmcguire5@gmail.com> |
|---|---|
| First post | 2023-03-07 15:38 -0600 |
| Last post | 2023-04-06 00:42 -0700 |
| Articles | 20 on this page of 146 — 22 participants |
Back to article view | Back to comp.lang.c++
"C++ on the Move" by Darryl K. Taft Lynn McGuire <lynnmcguire5@gmail.com> - 2023-03-07 15:38 -0600
Re: "C++ on the Move" by Darryl K. Taft legalize+jeeves@mail.xmission.com (Richard) - 2023-03-07 22:08 +0000
Re: "C++ on the Move" by Darryl K. Taft Lynn McGuire <lynnmcguire5@gmail.com> - 2023-03-07 16:25 -0600
Re: "C++ on the Move" by Darryl K. Taft legalize+jeeves@mail.xmission.com (Richard) - 2023-03-07 23:10 +0000
Re: "C++ on the Move" by Darryl K. Taft Paavo Helde <eesnimi@osa.pri.ee> - 2023-03-08 08:40 +0200
Re: "C++ on the Move" by Darryl K. Taft Lynn McGuire <lynnmcguire5@gmail.com> - 2023-04-05 19:30 -0500
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-07 23:21 -0800
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-03-08 16:10 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-08 19:47 +0100
Re: "C++ on the Move" by Darryl K. Taft Michael S <already5chosen@yahoo.com> - 2023-03-08 11:21 -0800
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-03-08 19:49 +0000
Re: "C++ on the Move" by Darryl K. Taft Michael S <already5chosen@yahoo.com> - 2023-03-08 12:08 -0800
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-08 09:52 -0800
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-08 10:18 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-08 20:45 +0100
Re: "C++ on the Move" by Darryl K. Taft "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-03-08 19:20 +0100
Re: "C++ on the Move" by Darryl K. Taft James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-03-08 14:10 -0500
Re: "C++ on the Move" by Darryl K. Taft "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-03-08 22:34 +0100
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-08 14:29 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-09 00:59 +0100
Re: "C++ on the Move" by Darryl K. Taft James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-03-08 18:11 -0500
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-08 12:28 -0800
Re: "C++ on the Move" by Darryl K. Taft Michael S <already5chosen@yahoo.com> - 2023-03-08 12:48 -0800
Re: "C++ on the Move" by Darryl K. Taft "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-03-08 22:40 +0100
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-09 01:12 +0100
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-08 16:27 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-09 13:52 +0100
Re: "C++ on the Move" by Darryl K. Taft Michael S <already5chosen@yahoo.com> - 2023-03-09 12:47 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-09 01:08 +0100
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-09 02:08 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-09 14:06 +0100
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-09 07:14 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-09 20:32 +0100
Re: "C++ on the Move" by Darryl K. Taft Michael S <already5chosen@yahoo.com> - 2023-03-09 12:42 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 00:30 +0100
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-03-10 15:01 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 16:38 +0100
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-03-10 16:36 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-11 10:43 +0100
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-08 12:59 -0800
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-09 03:03 -0800
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-09 12:12 -0800
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-09 19:20 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 10:36 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-10 04:27 -0800
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-10 05:13 -0800
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-10 06:05 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 15:59 +0100
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-10 15:14 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 16:45 +0100
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-10 16:02 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-13 11:45 +0100
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-13 12:00 +0000
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-13 12:26 +0000
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-13 15:00 +0000
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-13 15:18 +0000
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-13 16:00 +0000
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-13 18:43 +0000
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-14 09:26 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-14 13:30 +0100
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-14 16:16 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-14 17:49 +0100
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-14 17:14 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-14 23:05 +0100
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-15 08:39 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-15 17:31 +0100
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-15 17:11 +0000
Re: "C++ on the Move" by Darryl K. Taft Ben Bacarisse <ben.lists@bsb.me.uk> - 2023-03-15 00:10 +0000
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 14:52 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-13 20:17 +0100
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-13 19:31 +0000
Re: "C++ on the Move" by Darryl K. Taft Paavo Helde <eesnimi@osa.pri.ee> - 2023-03-14 00:01 +0200
Re: "C++ on the Move" by Darryl K. Taft gst <g.starck@gmail.com> - 2023-03-13 23:49 -0700
Re: "C++ on the Move" by Darryl K. Taft "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-03-14 11:04 +0100
Re: "C++ on the Move" by Darryl K. Taft gst <g.starck@gmail.com> - 2023-03-14 03:26 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-14 09:08 +0100
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 01:21 -0700
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 15:12 -0700
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-14 09:31 +0000
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-14 09:51 +0000
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-14 09:56 +0000
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-14 10:30 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-14 13:41 +0100
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 14:50 -0700
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 14:13 -0700
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-14 21:53 +0000
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-04-04 23:21 -0700
Re: "C++ on the Move" by Darryl K. Taft "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> - 2023-04-05 08:44 -0700
Re: "C++ on the Move" by Darryl K. Taft legalize+jeeves@mail.xmission.com (Richard) - 2023-04-05 15:47 +0000
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-04-05 16:33 +0000
Re: "C++ on the Move" by Darryl K. Taft richardthiebaud <thiebauddick2@aol.com> - 2023-04-05 12:53 -0400
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-04-05 17:19 +0000
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-04-05 13:47 -0700
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-04-06 08:12 +0000
Re: "C++ on the Move" by Darryl K. Taft Daniel <danielaparker@gmail.com> - 2023-04-06 05:23 -0700
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-04-06 08:09 +0000
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-07-20 10:02 -0700
Re: "C++ on the Move" by Darryl K. Taft Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-04-05 21:04 +0100
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-07-20 09:52 -0700
Re: "C++ on the Move" by Darryl K. Taft Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-07-20 21:01 +0100
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 08:57 -0700
Re: "C++ on the Move" by Darryl K. Taft Muttley@dastardlyhq.com - 2023-03-14 16:20 +0000
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-10 07:23 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 16:48 +0100
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 15:54 +0100
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-10 07:12 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 16:53 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-10 08:20 -0800
Re: "C++ on the Move" by Darryl K. Taft kalevi@kolttonen.fi (Kalevi Kolttonen) - 2023-03-10 16:48 +0000
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-12 11:54 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-12 09:29 -0700
Re: "C++ on the Move" by Darryl K. Taft Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-03-12 09:57 -0700
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-12 10:26 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-13 14:40 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-13 08:59 -0700
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-12 14:17 -0700
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-12 16:18 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-13 14:30 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-13 08:25 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-13 17:54 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-14 13:27 -0700
Re: "C++ on the Move" by Darryl K. Taft Paavo Helde <eesnimi@osa.pri.ee> - 2023-03-13 20:37 +0200
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-14 13:30 -0700
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-13 10:02 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-13 20:21 +0100
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-13 12:53 -0700
Re: "C++ on the Move" by Darryl K. Taft Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-03-14 01:17 -0700
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-14 09:55 +0100
Re: "C++ on the Move" by Darryl K. Taft scott@slp53.sl.home (Scott Lurndal) - 2023-03-10 16:27 +0000
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-10 11:33 -0800
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-10 11:14 -0800
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-11 04:10 -0800
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-12 12:06 +0100
Re: "C++ on the Move" by Darryl K. Taft Öö Tiib <ootiib@hot.ee> - 2023-03-12 09:29 -0700
Re: "C++ on the Move" by Darryl K. Taft Bonita Montero <Bonita.Montero@gmail.com> - 2023-03-09 15:26 +0100
Re: "C++ on the Move" by Darryl K. Taft Lynn McGuire <lynnmcguire5@gmail.com> - 2023-03-09 16:59 -0600
Re: "C++ on the Move" by Darryl K. Taft Bonita Montero <Bonita.Montero@gmail.com> - 2023-03-10 05:59 +0100
Re: "C++ on the Move" by Darryl K. Taft "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-03-10 09:17 +0100
Re: "C++ on the Move" by Darryl K. Taft Bonita Montero <Bonita.Montero@gmail.com> - 2023-03-10 13:38 +0100
Re: "C++ on the Move" by Darryl K. Taft Michael S <already5chosen@yahoo.com> - 2023-03-10 05:10 -0800
Re: "C++ on the Move" by Darryl K. Taft Bonita Montero <Bonita.Montero@gmail.com> - 2023-03-10 15:20 +0100
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 16:13 +0100
Re: "C++ on the Move" by Darryl K. Taft David Brown <david.brown@hesbynett.no> - 2023-03-10 10:44 +0100
Re: "C++ on the Move" by Darryl K. Taft Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-03-10 11:08 -0800
Re: "C++ on the Move" by Darryl K. Taft "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2023-03-12 11:42 +0100
Re: "C++ on the Move" by Darryl K. Taft "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-04-06 00:42 -0700
Page 6 of 8 — ← Prev page 1 2 3 4 5 [6] 7 8 Next page →
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2023-03-14 08:57 -0700 |
| Message-ID | <86wn3j72ca.fsf@linuxsc.com> |
| In reply to | #89706 |
Muttley@dastardlyhq.com writes: > Personally I understood the concepts of OO within probably 10 mins > of encountering it, functional programming didn't take much longer > to grok [...] That's incredible! > I must have programmed in at least 10 languages in my life but the > one I could never get my head around was Prolog and I still can't. > [...] On the other hand this statement is very credible.
[toc] | [prev] | [next] | [standalone]
| From | Muttley@dastardlyhq.com |
|---|---|
| Date | 2023-03-14 16:20 +0000 |
| Message-ID | <tuq6st$djjv$1@dont-email.me> |
| In reply to | #89750 |
On Tue, 14 Mar 2023 08:57:25 -0700 Tim Rentsch <tr.17687@z991.linuxsc.com> wrote: >Muttley@dastardlyhq.com writes: > >> Personally I understood the concepts of OO within probably 10 mins >> of encountering it, functional programming didn't take much longer >> to grok [...] > >That's incredible! Why? When I first learnt C++ it was analogous to C with structs with function pointers in them. Inheritance is hardly complicated and neither is polymorphism. Though if I'd encountered C++17 having never seen C++ before I probably wouldn't have bothered and would have gone down the Python or Java route instead. As for functional programming - its recursion + value based polymorphism. >> I must have programmed in at least 10 languages in my life but the >> one I could never get my head around was Prolog and I still can't. >> [...] > >On the other hand this statement is very credible. Go patronise someone else you plank.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-03-10 07:23 -0800 |
| Message-ID | <b5029d92-e075-41f3-a13b-0cf9148e1eedn@googlegroups.com> |
| In reply to | #89627 |
On Friday, 10 March 2023 at 14:59:48 UTC, David Brown wrote: > On 10/03/2023 14:13, Malcolm McLean wrote: > > On Friday, 10 March 2023 at 12:27:23 UTC, Öö Tiib wrote: > >> On Friday, 10 March 2023 at 11:36:26 UTC+2, David Brown wrote: > >> > >>> While it is true that pretty much all "big" processors and "big" OS's > >>> will trap on division by zero, the C and C++ world is very much wider > >>> than that. And it is absolutely correct for the standards to say > >>> nothing about how division by zero should be handled (i.e., it should be > >>> left undefined behaviour). > >>> > >> C and C++ do not want to be portable assemblers of whatever chips, > >> these want to be programming languages. From that viewpoint there > >> are no reason why something that hardware does not handle (despite > >> its cost to performance if handled is hard to notice) should be left > >> undefined behavior. > >> > > If we have > > > > int x; > > ... > > x++; > > > > Then most C/C++ programmers would say that it's essential that this compiles > > to > > Load accumulator with contents of memory location x. > > Increment accumulator. > > Store accumulator at memory location x. > > > No, most C or C++ programmers would /not/ say that. Most have no idea > what an "accumulator" is. (And most use processors that do not have an > accumulator.) Then there are the programmers who understand how the > languages are defined and how compilers work, and would certainly not > say that it is essential for a compiler to generate code like that. > > and not > > Load Aummulator with memory location x. > > Test Accumulator for equality to INT_MAX. > > Jump if positive to error handling code. > > Increment accumulator > > Store accumulator at memory location x. > > > If you are trying to say that most C and C++ programmers expect > compilers to generate efficient object code for simple source code, > without extra run-time checks, then say that. > That might not go in. I'm showing what the run time check would be, on a simple imaginary but realistic basic processor. That's more effective than talking in vague generalities.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-10 16:48 +0100 |
| Message-ID | <tufjfl$20omv$7@dont-email.me> |
| In reply to | #89632 |
On 10/03/2023 16:23, Malcolm McLean wrote: > On Friday, 10 March 2023 at 14:59:48 UTC, David Brown wrote: >> On 10/03/2023 14:13, Malcolm McLean wrote: >>> On Friday, 10 March 2023 at 12:27:23 UTC, Öö Tiib wrote: >>>> On Friday, 10 March 2023 at 11:36:26 UTC+2, David Brown wrote: >>>> >>>>> While it is true that pretty much all "big" processors and "big" OS's >>>>> will trap on division by zero, the C and C++ world is very much wider >>>>> than that. And it is absolutely correct for the standards to say >>>>> nothing about how division by zero should be handled (i.e., it should be >>>>> left undefined behaviour). >>>>> >>>> C and C++ do not want to be portable assemblers of whatever chips, >>>> these want to be programming languages. From that viewpoint there >>>> are no reason why something that hardware does not handle (despite >>>> its cost to performance if handled is hard to notice) should be left >>>> undefined behavior. >>>> >>> If we have >>> >>> int x; >>> ... >>> x++; >>> >>> Then most C/C++ programmers would say that it's essential that this compiles >>> to >>> Load accumulator with contents of memory location x. >>> Increment accumulator. >>> Store accumulator at memory location x. >>> >> No, most C or C++ programmers would /not/ say that. Most have no idea >> what an "accumulator" is. (And most use processors that do not have an >> accumulator.) Then there are the programmers who understand how the >> languages are defined and how compilers work, and would certainly not >> say that it is essential for a compiler to generate code like that. >>> and not >>> Load Aummulator with memory location x. >>> Test Accumulator for equality to INT_MAX. >>> Jump if positive to error handling code. >>> Increment accumulator >>> Store accumulator at memory location x. >>> >> If you are trying to say that most C and C++ programmers expect >> compilers to generate efficient object code for simple source code, >> without extra run-time checks, then say that. >> > That might not go in. I'm showing what the run time check would be, on > a simple imaginary but realistic basic processor. That's more effective than > talking in vague generalities. > Perhaps that is true.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-10 15:54 +0100 |
| Message-ID | <tufgbi$20omv$2@dont-email.me> |
| In reply to | #89616 |
On 10/03/2023 13:27, Öö Tiib wrote: > On Friday, 10 March 2023 at 11:36:26 UTC+2, David Brown wrote: >> On 10/03/2023 04:20, Öö Tiib wrote: >> >>> It is all about the trend. Most platforms trap on division by zero for >>> very long time. Yet the standards declare that they define nothing. >> No, most platforms do not trap on division by zero. >> >> The solid majority of different types of platforms that are programmed >> in C (and C++ gets this stuff from C) are small microcontrollers and >> other embedded processors. >> >> The solid majority of processor cores made and sold are small >> microcontrollers. >> > Their reasoning of hardware designers is such: "division by 0 is undefined > anyway and so we counted that setting all bits of result to 1 takes few less > internal gates than setting all bits to 0 does." > So the whole reason of such design is lack of market to trap on division > by zero there. Are you basing this on your intimate knowledge of the design decisions made by multiple cpu design teams? Everyone who has made it through primary school knows it makes no sense to divide by zero. It therefore makes no sense for a processor to aim for any particular result when someone tries to do the impossible. If a processor already has strong support for hardware exceptions as a debugging aid and for safe handling of multiple independent programs (as you get on a "big" general purpose cpu), then it is likely to have a trap of some sort on division by zero. If it is a chip optimised for low cost, size or power, for dedicated single-program microcontroller usage, then division by zero can be a "don't care". It might cause a reset, a hang, a nonsense result, a consistent and documented result - whatever. It would be a terrible idea for an efficient language to try to define what happens here, forcing compilers to generate pointless extra run-time checks just because some people have bugs in their code. > >> While it is true that pretty much all "big" processors and "big" OS's >> will trap on division by zero, the C and C++ world is very much wider >> than that. And it is absolutely correct for the standards to say >> nothing about how division by zero should be handled (i.e., it should be >> left undefined behaviour). >> > C and C++ do not want to be portable assemblers of whatever chips, > these want to be programming languages. I have no idea what you are talking about here. C and C++ are not, and never have been, "portable assemblers" - they are high level programming languages defined by standards and abstract machines, not the behaviour of particular processors. That is precisely why trying to retrofit the language standards to match particular processor hardware is such a bad idea. > From that viewpoint there > are no reason why something that hardware does not handle (despite > its cost to performance if handled is hard to notice) should be left > undefined behavior. > Of course there is. You have got this whole thing ass-backwards. (For any Americans here who don't understand that phrase, it means putting the donkey behind the cart.) C and C++ leave a number of things as "implementation dependent", when it is reasonable to expect that all hardware will be able to efficiently support /some/ behaviour, but the details of what the behaviour is can vary a lot. They leave some things as "undefined behaviour" when it is reasonable to expect that not all hardware can efficiently support /any/ defined and consistent behaviour. But there are many other reasons for having "undefined behaviour". That also includes cases where there simply is no sensible concept of "correct" behaviour, or even of expected and useful behaviour. Division by zero (for integers) is an example. No matter what definition you pick for it, it will be wrong. That includes trapping, or returning particular values, or setting processor flags. If you try to divide by zero, you have a bug in your code. The bug is /before/ the division. That applies equally to languages that do run-time checking and throw exceptions for division by zero - your code is nonsensical, and therefore wrong. Hardware cannot fix the bug in your program. The compiler cannot fix the bug, nor can run-time checks. (Sometimes these can help you find the bug.) It makes no sense for a language to try to define behaviour on division by zero - it is far better for the language to say "don't do that". Why someone would then want the language to say what will happen when you do something contrary to the rules of the language, is beyond my understanding. >> There is a strong tendency amongst programmers to think that all >> processors are x86 or ARM, and all OS's are Linux or Windows. >> Fortunately, the C and C++ standards committees are not as limited. >> >> (I am of the opinion that undefined behaviour is often a good thing for >> code that is clearly wrong, even if there were a consensus for how it >> might be treated in most hardware. I want division by zero to be >> undefined, because it means debug tools and analysers can be used to >> help track such bugs in the code. But that is an orthogonal issue.) >> > The only "positive" thing of pointless undefined behaviors is job > security. All the time I have wasted into memorising those and > learning usage of tools to track those down gives me advantage > on job market. But the work is anyway plentiful, largely badly or > not done and I could do something more interesting instead of > helping to track down some undefined behavior. What a load of drivel. No one wants /pointless/ undefined behaviour - that is a tautology. I have already explained why undefined behaviour in cases like division by zero and signed integer overflow is directly /useful/ and /beneficial/. If you don't accept my arguments there, fair enough. But at least accept that some programmers view things that way. No programmer has to memorise undefined behaviour. /Everything/ is undefined except the behaviours that are explicitly defined by the language (and/or documented extensions in a particular tool). You have to memories the /defined/ behaviours in C and C++ - this is called "learning the language". If you don't know what the code you are writing actually means, you are not doing your job correctly. (Of course we all make mistakes sometimes - part of the job is finding and fixing these.) And the examples discussed here, such as division by zero, are so obviously incorrect code that you should not have to learn the rules specifically. (There are certainly things in the C and C++ standards that are explicitly labelled as "undefined behaviour" that could be changed to required diagnostics for the compiler or linker, or perhaps to implementation-dependent behaviour or even fully defined behaviour. But division by 0 and signed integer overflow are not amongst them.)
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-03-10 07:12 -0800 |
| Message-ID | <014125b5-f10c-4373-a724-b843465d9b00n@googlegroups.com> |
| In reply to | #89626 |
On Friday, 10 March 2023 at 14:54:57 UTC, David Brown wrote: > On 10/03/2023 13:27, Öö Tiib wrote: > > > If you try to divide by zero, you have a bug in your code. The bug is > /before/ the division. That applies equally to languages that do > run-time checking and throw exceptions for division by zero - your code > is nonsensical, and therefore wrong. > > Hardware cannot fix the bug in your program. The compiler cannot fix > the bug, nor can run-time checks. (Sometimes these can help you find > the bug.) > > It makes no sense for a language to try to define behaviour on division > by zero - it is far better for the language to say "don't do that". Why > someone would then want the language to say what will happen when you do > something contrary to the rules of the language, is beyond my understanding. > There's a point in saying, for example, that division by zero will always terminate the program with an error message. Then if you do have a division by zero bug, that's easier to find than if the result is set to a random value. Rarely would you wish to generate this behaviour directly, but an exception is in an environment with poor diagnostic facilites. Then you can put a division by zero in the code, and if the error message triggers, you know that execution has reached that point. Sometime you ned to resort to these stratagems. If division by zero raises a non-signalling NaN, you might want to use that to generate a NaN, which sometimes can be useful.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-10 16:53 +0100 |
| Message-ID | <tufjpa$20omv$8@dont-email.me> |
| In reply to | #89629 |
On 10/03/2023 16:12, Malcolm McLean wrote: > On Friday, 10 March 2023 at 14:54:57 UTC, David Brown wrote: >> On 10/03/2023 13:27, Öö Tiib wrote: >>> >> If you try to divide by zero, you have a bug in your code. The bug is >> /before/ the division. That applies equally to languages that do >> run-time checking and throw exceptions for division by zero - your code >> is nonsensical, and therefore wrong. >> >> Hardware cannot fix the bug in your program. The compiler cannot fix >> the bug, nor can run-time checks. (Sometimes these can help you find >> the bug.) >> >> It makes no sense for a language to try to define behaviour on division >> by zero - it is far better for the language to say "don't do that". Why >> someone would then want the language to say what will happen when you do >> something contrary to the rules of the language, is beyond my understanding. >> > There's a point in saying, for example, that division by zero will always terminate > the program with an error message. Then if you do have a division by zero bug, > that's easier to find than if the result is set to a random value. Rarely would you > wish to generate this behaviour directly, but an exception is in an environment > with poor diagnostic facilites. Then you can put a division by zero in the code, > and if the error message triggers, you know that execution has reached that point. > Sometime you ned to resort to these stratagems. > I agree that trapping can be useful as a debugging aid - though it is important to remember that the bug is /not/ at the point when the trap comes, but some unknown time prior to that. But it would be wrong for the language to /require/ such behaviour. You can be looking for different features at different stages of development, or for different kinds of program and different kinds of target. Leaving the behaviour undefined in the standards gives users and toolchain developers the freedom to provide options and better features, while defining the behaviour limits things and leaves some platforms obliged to generate inefficient code unnecessarily, while simultaneously stopping more powerful tools from proving more aid to the developer. > If division by zero raises a non-signalling NaN, you might want to use that to generate > a NaN, which sometimes can be useful. If you are talking about floating point here, the mathematical and programming model is significantly different from integer arithmetic.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2023-03-10 08:20 -0800 |
| Message-ID | <46541a68-9cb6-44eb-a2e1-78f1819822f5n@googlegroups.com> |
| In reply to | #89626 |
On Friday, 10 March 2023 at 16:54:57 UTC+2, David Brown wrote: > On 10/03/2023 13:27, Öö Tiib wrote: > > On Friday, 10 March 2023 at 11:36:26 UTC+2, David Brown wrote: > >> On 10/03/2023 04:20, Öö Tiib wrote: > >> > >>> It is all about the trend. Most platforms trap on division by zero for > >>> very long time. Yet the standards declare that they define nothing. > >> No, most platforms do not trap on division by zero. > >> > >> The solid majority of different types of platforms that are programmed > >> in C (and C++ gets this stuff from C) are small microcontrollers and > >> other embedded processors. > >> > >> The solid majority of processor cores made and sold are small > >> microcontrollers. > >> > > Their reasoning of hardware designers is such: "division by 0 is undefined > > anyway and so we counted that setting all bits of result to 1 takes few less > > internal gates than setting all bits to 0 does." > > So the whole reason of such design is lack of market to trap on division > > by zero there. > > Are you basing this on your intimate knowledge of the design decisions > made by multiple cpu design teams? > > Everyone who has made it through primary school knows it makes no sense > to divide by zero. It therefore makes no sense for a processor to aim > for any particular result when someone tries to do the impossible. If a > processor already has strong support for hardware exceptions as a > debugging aid and for safe handling of multiple independent programs (as > you get on a "big" general purpose cpu), then it is likely to have a > trap of some sort on division by zero. If it is a chip optimised for > low cost, size or power, for dedicated single-program microcontroller > usage, then division by zero can be a "don't care". It might cause a > reset, a hang, a nonsense result, a consistent and documented result - > whatever. > I did nowhere argue that division by zero is correct thing to do. > It would be a terrible idea for an efficient language to try to define > what happens here, forcing compilers to generate pointless extra > run-time checks just because some people have bugs in their code. > I understand that you do not want that undefined behavior is reduced. > > > >> While it is true that pretty much all "big" processors and "big" OS's > >> will trap on division by zero, the C and C++ world is very much wider > >> than that. And it is absolutely correct for the standards to say > >> nothing about how division by zero should be handled (i.e., it should be > >> left undefined behaviour). > >> > > C and C++ do not want to be portable assemblers of whatever chips, > > these want to be programming languages. > > I have no idea what you are talking about here. C and C++ are not, and > never have been, "portable assemblers" - they are high level programming > languages defined by standards and abstract machines, not the behaviour > of particular processors. That is precisely why trying to retrofit the > language standards to match particular processor hardware is such a bad > idea. > These have never been. So language should not consider what particular processor hardware does. > > From that viewpoint there > > are no reason why something that hardware does not handle (despite > > its cost to performance if handled is hard to notice) should be left > > undefined behavior. > > > Of course there is. You have got this whole thing ass-backwards. (For > any Americans here who don't understand that phrase, it means putting > the donkey behind the cart.) > > C and C++ leave a number of things as "implementation dependent", when > it is reasonable to expect that all hardware will be able to efficiently > support /some/ behaviour, but the details of what the behaviour is can > vary a lot. > > They leave some things as "undefined behaviour" when it is reasonable to > expect that not all hardware can efficiently support /any/ defined and > consistent behaviour. > > But there are many other reasons for having "undefined behaviour". That > also includes cases where there simply is no sensible concept of > "correct" behaviour, or even of expected and useful behaviour. Division > by zero (for integers) is an example. No matter what definition you > pick for it, it will be wrong. That includes trapping, or returning > particular values, or setting processor flags. > > If you try to divide by zero, you have a bug in your code. The bug is > /before/ the division. That applies equally to languages that do > run-time checking and throw exceptions for division by zero - your code > is nonsensical, and therefore wrong. > > Hardware cannot fix the bug in your program. The compiler cannot fix > the bug, nor can run-time checks. (Sometimes these can help you find > the bug.) > > It makes no sense for a language to try to define behaviour on division > by zero - it is far better for the language to say "don't do that". Why > someone would then want the language to say what will happen when you do > something contrary to the rules of the language, is beyond my understanding. > That is building misrepresentation and then saying that the result is beyond your understanding. I neither do nor want to do anything contrary to the rules of language. I want the rules of language to become better. Typical case is that programmer did invoke undefined behavior but program appears to work like he wanted ... until it does not. Who benefits from that? > >> There is a strong tendency amongst programmers to think that all > >> processors are x86 or ARM, and all OS's are Linux or Windows. > >> Fortunately, the C and C++ standards committees are not as limited. > >> > >> (I am of the opinion that undefined behaviour is often a good thing for > >> code that is clearly wrong, even if there were a consensus for how it > >> might be treated in most hardware. I want division by zero to be > >> undefined, because it means debug tools and analysers can be used to > >> help track such bugs in the code. But that is an orthogonal issue.) > >> > > The only "positive" thing of pointless undefined behaviors is job > > security. All the time I have wasted into memorising those and > > learning usage of tools to track those down gives me advantage > > on job market. But the work is anyway plentiful, largely badly or > > not done and I could do something more interesting instead of > > helping to track down some undefined behavior. > What a load of drivel. > > No one wants /pointless/ undefined behaviour - that is a tautology. I > have already explained why undefined behaviour in cases like division by > zero and signed integer overflow is directly /useful/ and /beneficial/. > If you don't accept my arguments there, fair enough. But at least > accept that some programmers view things that way. > I have observed no benefit of undefined behavior ever. I would still leave some kind of attribute [[unsafe]] for people who want it. > No programmer has to memorise undefined behaviour. /Everything/ is > undefined except the behaviours that are explicitly defined by the > language (and/or documented extensions in a particular tool). You have > to memories the /defined/ behaviours in C and C++ - this is called > "learning the language". If you don't know what the code you are > writing actually means, you are not doing your job correctly. (Of > course we all make mistakes sometimes - part of the job is finding and > fixing these.) > That makes those to take so lot of years to learn. You think that the 1000 page standard in that cryptic language lawyer slang said something about some case but then you check and no it did not. Maybe elsewhere ... none there too. It may take some years before you face the situation but sooner or later there will be. > And the examples discussed here, such as division by zero, are so > obviously incorrect code that you should not have to learn the rules > specifically. > > (There are certainly things in the C and C++ standards that are > explicitly labelled as "undefined behaviour" that could be changed to > required diagnostics for the compiler or linker, or perhaps to > implementation-dependent behaviour or even fully defined behaviour. But > division by 0 and signed integer overflow are not amongst them.) > Undefined behavior is neither obvious nor certain. Incorrectness results with program doing whatever only because rules say so. Throwing from function "void f() noexcept;" is also obviously incorrect yet C++ standard requires calling std::terminate() on that case. There are reasons why intrinsics like __builtin_saddll_overflow are there. Only that I do not want the code to call function named in Orcish and check a bool. I would like guaranteed terminate, signal or exception.
[toc] | [prev] | [next] | [standalone]
| From | kalevi@kolttonen.fi (Kalevi Kolttonen) |
|---|---|
| Date | 2023-03-10 16:48 +0000 |
| Message-ID | <tufn1j$21l1l$1@dont-email.me> |
| In reply to | #89640 |
Öö Tiib <ootiib@hot.ee> wrote: > [...] I neither do nor want to do anything contrary to > the rules of language. I want the rules of language to become better. > Typical case is that programmer did invoke undefined behavior but > program appears to work like he wanted ... until it does not. Who > benefits from that? Apologies for mentioning UB in C in a C++ newsgroup, but everybody needs to realize that it is very important to avoid UB at all costs. The following is a true horror story and much worse things than this could happen. When I was working as a system administrator, we used Cyrus IMAPD as email storage. I guess the Cyrus version was 2.4.17 and if I remember right, at the time it was running on Red Hat Enterprise Linux 7. This Cyrus version had worked flawlessly for years, but unfortunately the C code had UB. In the code handling mailboxes database, I think I remember there was an incorrect invocation of strcpy, a well-known C standard library function. The strcpy manual page clearly states: The strings may not overlap, and the destination string dest must be large enough to receive the copy The strings did overlap, but nobody ever noticed it, since glibc implementation of strcpy guarded against this mistake. As we know, with UB, anything could happen, including producing the correct behavior as intended by the programmer. Then one day glibc maintainers decided to optimize their AMD64 implementation of strcpy, and the guards for detecting overlapping strings were removed. Next thing we knew was that the mailboxes database was getting more and more corrupted, ending up in such a bad state that Cyrus IMAPD would no longer start. It was not a fun task to restore the mailboxes database into working order. Lesson: Never rely on UB! br, KK
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-12 11:54 +0100 |
| Message-ID | <tukb1f$31hii$1@dont-email.me> |
| In reply to | #89640 |
On 10/03/2023 17:20, Öö Tiib wrote: > Undefined behavior is neither obvious nor certain. Incorrectness results > with program doing whatever only because rules say so. Throwing from > function "void f() noexcept;" is also obviously incorrect yet C++ standard > requires calling std::terminate() on that case. > There are reasons why intrinsics like __builtin_saddll_overflow are > there. Only that I do not want the code to call function named in Orcish > and check a bool. I would like guaranteed terminate, signal or exception. > Even if it has not always been clear in this thread, I think we can agree on quite a number of things: Any code that attempts to execute code with undefined behaviour, is buggy. In some cases, it might work well enough for a while and then fail due to later changes (such as in the anecdote about strcpy). Undefined behaviour which could be caught at compile/link time without unreasonable compiler effort, should be caught there. Some kinds of undefined behaviour - bugs in the code - could be detected by run-time checks, with or without hardware support. If hardware can handle the checks with no overhead, that's great. If there is overhead in code speed or missed optimisation, that must be balanced against the benefits of catching bugs. (If you don't agree on these points, I hope you'll say so.) I am of the opinion that if a language cannot define a particular behaviour in a correct manner, then it should be left undefined. I see no point in a language insisting on incorrect behaviour. Leaving it undefined gives the implementation freedom to optimise on the assumption that it does not happen when the user is looking for optimal efficiency, and also to allow extra checks and debugging aids to help developers find problems in their code. Defining behaviour limits that, while not being able to give the programmer any useful benefits. Let's take a couple of examples. For signed integer overflow, there are two realistic possible definitions for behaviour - two's complement wrapping, and trapping. (There are other possibilities, such as saturation, but that's going to be inefficient on most hardware.) Some languages, such as Java, use wrapping. For some simple expressions, that is efficient on all realistic hardware - but for many expressions it limits optimisations and is therefore less efficient. It guarantees an incorrect answer in a lot of situations. And it stops tools from being able to add checks and traps for bug-hunting aids, as the language does not consider overflow to be an error. Thus it is often worse than useless as a feature for general coding, even though it occasionally helps. Some languages, such as Ada, consider overflow to be a run-time error that must be detected, leading to an exception or other trapping behaviour. That's great for debugging, but can be very inefficient in practice, even when the programmer knows the calculation cannot overflow (if the compiler can /prove/ there can be no overflow, it can omit the checks). And when such exceptions are part of the defined behaviour, the program needs to handle them - in many cases, there is no sensible choice of behaviour for the program when it sees such errors, and any code paths handling them are not seriously considered or seriously tested. Other languages, such as Python, do not have overflow - the integer types are extendable and grow as needed. That means you always get the correct answer, but at such considerable run-time cost that it is not appropriate for a language aimed at efficient compiled code. So there are pros and cons of these possible ways of handling overflow, but everything other than "undefined behaviour that is assumed not to happen in correct code" has a cost. For something as low-level and common as integer arithmetic, any cost can quickly become significant. Whereas other languages are often fixed in their handling of overflow, C++ is flexible - you can make your own classes to handle overflow just the way you want. The language does not impose any choice on the users, but provides the mechanisms to let you make whatever kinds of integers you want with whatever overflow handling you want. (You can also do C-style manual checks whenever you feel the need.) As another common example of undefined behaviour, let's look at dereferencing invalid pointers - such as attempting to access array elements outside of the array's bounds. This is UB in C and C++. On bigger systems, hardware (MMU) and software (the OS) combine to give near zero-overhead trapping for accesses that are far out of bounds, outside the memory space of the process. This is vital for secure and reliable multi-program and multi-user systems. But it could not be behaviour defined or required in the language standard, because many smaller systems (typically single-program devices) cannot do anything like this, and even on big systems the mechanisms can vary wildly. For "close miss" errors, where the target address is inside the processes' memory spaces, there is no general low-cost mechanism to detect and prevent such invalid accesses. The language would require "fat pointers" everywhere, with very different ways of dealing with accesses, array slices, etc. Basically, the language would have to remove the concepts of "pointer" and direct references entirely - fine for slow, safe, interpreted Python but not appropriate for C or C++. Leaving the behaviour undefined means tools can add checking (like memory sanitizers or valgrind) for debugging, and optimise code that you know is correct. Note also that there is no general way to determine if an access will be a "close miss" or outside the processes' memory spaces. And again, you can add whatever behaviour and checks you like for your own use. Put in checks manually. Make your own "array" class that has bound-checked indexing by default, if that's what suits you. "Undefined behaviour" is key to how C and C++ work, and what makes them great languages. It is utterly essential to the philosophy of "zero overhead" and not paying for things you don't use. As a C and C++ programmer, it is /your/ choice and /your/ responsibility to make sure the code is correct, and to choose whatever level of extra checking you feel appropriate to the task in hand. With C++ you can make your classes to automate this as needed - UB is vital to giving you that freedom.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2023-03-12 09:29 -0700 |
| Message-ID | <a23c85e1-1b42-4f63-9e64-f7621606764an@googlegroups.com> |
| In reply to | #89668 |
On Sunday, 12 March 2023 at 12:54:57 UTC+2, David Brown wrote: > On 10/03/2023 17:20, Öö Tiib wrote: > > > Undefined behavior is neither obvious nor certain. Incorrectness results > > with program doing whatever only because rules say so. Throwing from > > function "void f() noexcept;" is also obviously incorrect yet C++ standard > > requires calling std::terminate() on that case. > > There are reasons why intrinsics like __builtin_saddll_overflow are > > there. Only that I do not want the code to call function named in Orcish > > and check a bool. I would like guaranteed terminate, signal or exception. > > > Even if it has not always been clear in this thread, I think we can > agree on quite a number of things: > > Any code that attempts to execute code with undefined behaviour, is > buggy. In some cases, it might work well enough for a while and then > fail due to later changes (such as in the anecdote about strcpy). > > Undefined behaviour which could be caught at compile/link time without > unreasonable compiler effort, should be caught there. > > Some kinds of undefined behaviour - bugs in the code - could be detected > by run-time checks, with or without hardware support. If hardware can > handle the checks with no overhead, that's great. If there is overhead > in code speed or missed optimisation, that must be balanced against the > benefits of catching bugs. > > (If you don't agree on these points, I hope you'll say so.) > Basically I agree just that the trend is that even the bugs that are detected on hardware level are ignored. That is like the effort of hardware designers was wasted. Instead compilers often generate code that bypasses those hardware checks and does something odd or even what programmers did expect instead. So code generation is too much balanced towards not catching bugs. That is pointless philosophy of unreliability. > I am of the opinion that if a language cannot define a particular > behaviour in a correct manner, then it should be left undefined. I see > no point in a language insisting on incorrect behaviour. Leaving it > undefined gives the implementation freedom to optimise on the assumption > that it does not happen when the user is looking for optimal efficiency, > and also to allow extra checks and debugging aids to help developers > find problems in their code. Defining behaviour limits that, while not > being able to give the programmer any useful benefits. > The integer arithmetic has been very rarely important to performance for very long time. It was already in nineties when people did show that with simpler compression algorithms uncompressing can be quicker than memcpy between two uncompressed buffers. Changes in integer arithmetic are rarely needed for performance but often for correctness. > Let's take a couple of examples. For signed integer overflow, there are > two realistic possible definitions for behaviour - two's complement > wrapping, and trapping. (There are other possibilities, such as > saturation, but that's going to be inefficient on most hardware.) Some > languages, such as Java, use wrapping. For some simple expressions, > that is efficient on all realistic hardware - but for many expressions > it limits optimisations and is therefore less efficient. It guarantees > an incorrect answer in a lot of situations. And it stops tools from > being able to add checks and traps for bug-hunting aids, as the language > does not consider overflow to be an error. Thus it is often worse than > useless as a feature for general coding, even though it occasionally helps. > > Some languages, such as Ada, consider overflow to be a run-time error > that must be detected, leading to an exception or other trapping > behaviour. That's great for debugging, but can be very inefficient in > practice, even when the programmer knows the calculation cannot overflow > (if the compiler can /prove/ there can be no overflow, it can omit the > checks). And when such exceptions are part of the defined behaviour, > the program needs to handle them - in many cases, there is no sensible > choice of behaviour for the program when it sees such errors, and any > code paths handling them are not seriously considered or seriously tested. > > Other languages, such as Python, do not have overflow - the integer > types are extendable and grow as needed. That means you always get the > correct answer, but at such considerable run-time cost that it is not > appropriate for a language aimed at efficient compiled code. > > So there are pros and cons of these possible ways of handling overflow, > but everything other than "undefined behaviour that is assumed not to > happen in correct code" has a cost. For something as low-level and > common as integer arithmetic, any cost can quickly become significant. > > Whereas other languages are often fixed in their handling of overflow, > C++ is flexible - you can make your own classes to handle overflow just > the way you want. The language does not impose any choice on the users, > but provides the mechanisms to let you make whatever kinds of integers > you want with whatever overflow handling you want. (You can also do > C-style manual checks whenever you feel the need.) > You reply to where I mentioned that programmers can write their own trapping, (or saturating or wrapping) arithmetic using compiler intrinsics. Those are not part of C++ language. C++ language is as unhelpful as it only can. There is only undefined behavior available. How is that flexible? So compiler writers have attempted to at least help a bit. > As another common example of undefined behaviour, let's look at > dereferencing invalid pointers - such as attempting to access array > elements outside of the array's bounds. This is UB in C and C++. On > bigger systems, hardware (MMU) and software (the OS) combine to give > near zero-overhead trapping for accesses that are far out of bounds, > outside the memory space of the process. This is vital for secure and > reliable multi-program and multi-user systems. But it could not be > behaviour defined or required in the language standard, because many > smaller systems (typically single-program devices) cannot do anything > like this, and even on big systems the mechanisms can vary wildly. > > For "close miss" errors, where the target address is inside the > processes' memory spaces, there is no general low-cost mechanism to > detect and prevent such invalid accesses. The language would require > "fat pointers" everywhere, with very different ways of dealing with > accesses, array slices, etc. Basically, the language would have to > remove the concepts of "pointer" and direct references entirely - fine > for slow, safe, interpreted Python but not appropriate for C or C++. > Leaving the behaviour undefined means tools can add checking (like > memory sanitizers or valgrind) for debugging, and optimise code that you > know is correct. Note also that there is no general way to determine if > an access will be a "close miss" or outside the processes' memory spaces. > > And again, you can add whatever behaviour and checks you like for your > own use. Put in checks manually. Make your own "array" class that has > bound-checked indexing by default, if that's what suits you. > For those other examples there are even no compiler intrinsics. Can do basically nothing but to use the skills accumulated with decades to help out. Again, even if to remove quarter of undefined behaviors the language would become simply better by that quarter. There are no good or beneficial undefined behaviors. > "Undefined behaviour" is key to how C and C++ work, and what makes them > great languages. It is utterly essential to the philosophy of "zero > overhead" and not paying for things you don't use. As a C and C++ > programmer, it is /your/ choice and /your/ responsibility to make sure > the code is correct, and to choose whatever level of extra checking you > feel appropriate to the task in hand. With C++ you can make your > classes to automate this as needed - UB is vital to giving you that freedom. > All people are fallible. They make mistakes with often boring stuff that compiler could refuse or that hardware does already trap. It is no way super "key feature" that those opportunities are ignored.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-03-12 09:57 -0700 |
| Message-ID | <e0920e3b-4a09-4f25-ac3a-b8753226e638n@googlegroups.com> |
| In reply to | #89675 |
On Sunday, 12 March 2023 at 16:29:30 UTC, Öö Tiib wrote: > > The integer arithmetic has been very rarely important to performance > for very long time. It was already in nineties when people did show that > with simpler compression algorithms uncompressing can be quicker > than memcpy between two uncompressed buffers. Changes in integer > arithmetic are rarely needed for performance but often for correctness. > On a big modern processor, the bottleneck will be memory access, in particular cache misses. However C and C++ are not used exclusively for big processors.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2023-03-12 10:26 -0700 |
| Message-ID | <d5b5eef5-1418-4328-a5b3-5120bbf25ebdn@googlegroups.com> |
| In reply to | #89677 |
On Sunday, 12 March 2023 at 18:57:17 UTC+2, Malcolm McLean wrote: > On Sunday, 12 March 2023 at 16:29:30 UTC, Öö Tiib wrote: > > > > The integer arithmetic has been very rarely important to performance > > for very long time. It was already in nineties when people did show that > > with simpler compression algorithms uncompressing can be quicker > > than memcpy between two uncompressed buffers. Changes in integer > > arithmetic are rarely needed for performance but often for correctness. > > > On a big modern processor, the bottleneck will be memory access, in > particular cache misses. > However C and C++ are not used exclusively for big processors. > From that does not follow that integer arithmetic is bottle-neck on small processors. Lets say your small processor does not have much memory but can do about 16 millions operations per second. What the heck it does for integer arithmetic to become bottle-neck for it?
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-13 14:40 +0100 |
| Message-ID | <tun951$3ph9u$1@dont-email.me> |
| In reply to | #89679 |
On 12/03/2023 18:26, Öö Tiib wrote: > On Sunday, 12 March 2023 at 18:57:17 UTC+2, Malcolm McLean wrote: >> On Sunday, 12 March 2023 at 16:29:30 UTC, Öö Tiib wrote: >>> >>> The integer arithmetic has been very rarely important to performance >>> for very long time. It was already in nineties when people did show that >>> with simpler compression algorithms uncompressing can be quicker >>> than memcpy between two uncompressed buffers. Changes in integer >>> arithmetic are rarely needed for performance but often for correctness. >>> >> On a big modern processor, the bottleneck will be memory access, in >> particular cache misses. >> However C and C++ are not used exclusively for big processors. >> > From that does not follow that integer arithmetic is bottle-neck on > small processors. Lets say your small processor does not have much > memory but can do about 16 millions operations per second. What the > heck it does for integer arithmetic to become bottle-neck for it? Let's rather say it is doing 16 operations in a microsecond - suddenly a clock cycle more or less makes a /huge/ difference. Or it is doing 1000 loops of an FFT calculation every millisecond - 15 cycles in the inner loop means success, 17 cycles means failure. Remember, no one is arguing for getting the right answers out of calculations with overflows. I am suggesting that programmers beat the "garbage in, garbage out" situation by not putting in garbage in the first place. There there is no benefit from all that extra effort for "garbage in, error message out". Programmers should put their checks and controls in the /right/ places, not rely on a nanny language to double-check their homework. Instead of asking the language to do something as silly as adding two numbers whose sum is out of range of the target type, make sure the numbers are right in the first place, and that the target type is appropriate. And if you want to put in checks, do so in the part of the code that might be wrong, not later on.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2023-03-13 08:59 -0700 |
| Message-ID | <397cc17d-18f6-4f10-a159-f5af47640816n@googlegroups.com> |
| In reply to | #89709 |
On Monday, 13 March 2023 at 15:41:05 UTC+2, David Brown wrote: > On 12/03/2023 18:26, Öö Tiib wrote: > > On Sunday, 12 March 2023 at 18:57:17 UTC+2, Malcolm McLean wrote: > >> On Sunday, 12 March 2023 at 16:29:30 UTC, Öö Tiib wrote: > >>> > >>> The integer arithmetic has been very rarely important to performance > >>> for very long time. It was already in nineties when people did show that > >>> with simpler compression algorithms uncompressing can be quicker > >>> than memcpy between two uncompressed buffers. Changes in integer > >>> arithmetic are rarely needed for performance but often for correctness. > >>> > >> On a big modern processor, the bottleneck will be memory access, in > >> particular cache misses. > >> However C and C++ are not used exclusively for big processors. > >> > > From that does not follow that integer arithmetic is bottle-neck on > > small processors. Lets say your small processor does not have much > > memory but can do about 16 millions operations per second. What the > > heck it does for integer arithmetic to become bottle-neck for it? > Let's rather say it is doing 16 operations in a microsecond - suddenly a > clock cycle more or less makes a /huge/ difference. Or it is doing 1000 > loops of an FFT calculation every millisecond - 15 cycles in the inner > loop means success, 17 cycles means failure. > > Remember, no one is arguing for getting the right answers out of > calculations with overflows. Refusing to do is also correct and valuable answer. I estimate that about 30% of "information" around us is deliberate misinformation and 60% is utter garbage or naively repeating that misinformation. > I am suggesting that programmers beat the > "garbage in, garbage out" situation by not putting in garbage in the > first place. Typically they beat it by unaided manual checking. Sometimes they forget and that results with things like security breaches and jpeg viruses. > There there is no benefit from all that extra effort for > "garbage in, error message out". Programmers should put their checks > and controls in the /right/ places, not rely on a nanny language to > double-check their homework. Instead of asking the language to do > something as silly as adding two numbers whose sum is out of range of > the target type, make sure the numbers are right in the first place, and > that the target type is appropriate. And if you want to put in checks, > do so in the part of the code that might be wrong, not later on. Homework deals with isolated, internal problems but real software typically gets the data from (potentially gruel world) outside not from hands of programmer or teacher. Programmer has of course check himself instead of declaring limits to types. I suspect that in few years these manual checks face the destiny of "register" and "inline" and turn into hints that compilers ignore.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2023-03-12 14:17 -0700 |
| Message-ID | <87jzzlpt34.fsf@nosuchdomain.example.com> |
| In reply to | #89675 |
Öö Tiib <ootiib@hot.ee> writes:
[...]
> For those other examples there are even no compiler intrinsics.
> Can do basically nothing but to use the skills accumulated with
> decades to help out. Again, even if to remove quarter of undefined
> behaviors the language would become simply better by that quarter.
> There are no good or beneficial undefined behaviors.
[...]
Which brings us back to the point I tried to make earlier.
Upthread, you wrote:
Most people agree that C++ contains too lot of features. They only
differ by opinion where to cut. I would put most effort into places
where it says "undefined behavior". I think half of such places can
be replaced with "program is ill formed", "std::terminate is called"
or one of the features that lead to described situation can be cut
out (as badly thought thru).
Now you talk about removing a quarter of undefined behaviors.
Leaving aside for the moment the fact that most cases of undefined
behavior are implicit, I was hoping for some indication of *which* cases
you think can be removed. I agree that there are some, but I'm
skeptical that it would be practical to remove as many has half.
Any comment on that?
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2023-03-12 16:18 -0700 |
| Message-ID | <849fb442-7dff-4b16-8bd2-2d95864924cdn@googlegroups.com> |
| In reply to | #89688 |
On Sunday, 12 March 2023 at 23:18:08 UTC+2, Keith Thompson wrote:
> Öö Tiib <oot...@hot.ee> writes:
> [...]
> > For those other examples there are even no compiler intrinsics.
> > Can do basically nothing but to use the skills accumulated with
> > decades to help out. Again, even if to remove quarter of undefined
> > behaviors the language would become simply better by that quarter.
> > There are no good or beneficial undefined behaviors.
> [...]
>
> Which brings us back to the point I tried to make earlier.
>
> Upthread, you wrote:
>
> Most people agree that C++ contains too lot of features. They only
> differ by opinion where to cut. I would put most effort into places
> where it says "undefined behavior". I think half of such places can
> be replaced with "program is ill formed", "std::terminate is called"
> or one of the features that lead to described situation can be cut
> out (as badly thought thru).
>
> Now you talk about removing a quarter of undefined behaviors.
>
> Leaving aside for the moment the fact that most cases of undefined
> behavior are implicit, I was hoping for some indication of *which* cases
> you think can be removed. I agree that there are some, but I'm
> skeptical that it would be practical to remove as many has half.
>
> Any comment on that?
I do not think that majority of cases are implicit. Or may be there are
but the implicit cases are very rarely met. Yes, I think that about half
can be removed. May be that half is too lot of work then even quarter
would help in major way. For example that:
int& foo(int x) {return x;}
There must be is good reason why that is not an error (and even
not undefined behavior).
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-13 14:30 +0100 |
| Message-ID | <tun8gt$3pddq$1@dont-email.me> |
| In reply to | #89675 |
On 12/03/2023 17:29, Öö Tiib wrote:
> On Sunday, 12 March 2023 at 12:54:57 UTC+2, David Brown wrote:
>> On 10/03/2023 17:20, Öö Tiib wrote:
>>
>>> Undefined behavior is neither obvious nor certain. Incorrectness results
>>> with program doing whatever only because rules say so. Throwing from
>>> function "void f() noexcept;" is also obviously incorrect yet C++ standard
>>> requires calling std::terminate() on that case.
>>> There are reasons why intrinsics like __builtin_saddll_overflow are
>>> there. Only that I do not want the code to call function named in Orcish
>>> and check a bool. I would like guaranteed terminate, signal or exception.
>>>
>> Even if it has not always been clear in this thread, I think we can
>> agree on quite a number of things:
>>
>> Any code that attempts to execute code with undefined behaviour, is
>> buggy. In some cases, it might work well enough for a while and then
>> fail due to later changes (such as in the anecdote about strcpy).
>>
>> Undefined behaviour which could be caught at compile/link time without
>> unreasonable compiler effort, should be caught there.
>>
>> Some kinds of undefined behaviour - bugs in the code - could be detected
>> by run-time checks, with or without hardware support. If hardware can
>> handle the checks with no overhead, that's great. If there is overhead
>> in code speed or missed optimisation, that must be balanced against the
>> benefits of catching bugs.
>>
>> (If you don't agree on these points, I hope you'll say so.)
>>
> Basically I agree just that the trend is that even the bugs that are detected
> on hardware level are ignored. That is like the effort of hardware designers
> was wasted. Instead compilers often generate code that bypasses those
> hardware checks and does something odd or even what programmers
> did expect instead. So code generation is too much balanced towards
> not catching bugs. That is pointless philosophy of unreliability.
>
>> I am of the opinion that if a language cannot define a particular
>> behaviour in a correct manner, then it should be left undefined. I see
>> no point in a language insisting on incorrect behaviour. Leaving it
>> undefined gives the implementation freedom to optimise on the assumption
>> that it does not happen when the user is looking for optimal efficiency,
>> and also to allow extra checks and debugging aids to help developers
>> find problems in their code. Defining behaviour limits that, while not
>> being able to give the programmer any useful benefits.
>>
> The integer arithmetic has been very rarely important to performance
> for very long time. It was already in nineties when people did show that
> with simpler compression algorithms uncompressing can be quicker
> than memcpy between two uncompressed buffers. Changes in integer
> arithmetic are rarely needed for performance but often for correctness.
>
That is, at best, a very narrow view - at worst it is just wrong.
It is certainly the case that memory speeds have not increased at close
to the rate of the increase in processor speeds - for large processors.
But, again, you are missing the big picture and only considering one
type of processor. It's a different world outside of your PC.
You are also failing to consider that the compression and decompression
relies heavily on integer arithmetic, as does all pointer arithmetic.
It is /only/ because C and C++ compilers can generate fast code for
integer arithmetic that the compression and decompression algorithms are
fast enough to make your benchmarks run quickly.
I'll happily agree that code efficiency is not important in all code.
And I am more than happy to agree that code correctness is far more
important than code efficiency.
But I do not accept that all correct code should be made to run
inefficiently just because some code is incorrect. If you want to do
that, pick a different programming language with a different balance
between efficiency and treatment of potential errors in code - C and C++
are not the languages for you.
>> Let's take a couple of examples. For signed integer overflow, there are
>> two realistic possible definitions for behaviour - two's complement
>> wrapping, and trapping. (There are other possibilities, such as
>> saturation, but that's going to be inefficient on most hardware.) Some
>> languages, such as Java, use wrapping. For some simple expressions,
>> that is efficient on all realistic hardware - but for many expressions
>> it limits optimisations and is therefore less efficient. It guarantees
>> an incorrect answer in a lot of situations. And it stops tools from
>> being able to add checks and traps for bug-hunting aids, as the language
>> does not consider overflow to be an error. Thus it is often worse than
>> useless as a feature for general coding, even though it occasionally helps.
>>
>> Some languages, such as Ada, consider overflow to be a run-time error
>> that must be detected, leading to an exception or other trapping
>> behaviour. That's great for debugging, but can be very inefficient in
>> practice, even when the programmer knows the calculation cannot overflow
>> (if the compiler can /prove/ there can be no overflow, it can omit the
>> checks). And when such exceptions are part of the defined behaviour,
>> the program needs to handle them - in many cases, there is no sensible
>> choice of behaviour for the program when it sees such errors, and any
>> code paths handling them are not seriously considered or seriously tested.
>>
>> Other languages, such as Python, do not have overflow - the integer
>> types are extendable and grow as needed. That means you always get the
>> correct answer, but at such considerable run-time cost that it is not
>> appropriate for a language aimed at efficient compiled code.
>>
>> So there are pros and cons of these possible ways of handling overflow,
>> but everything other than "undefined behaviour that is assumed not to
>> happen in correct code" has a cost. For something as low-level and
>> common as integer arithmetic, any cost can quickly become significant.
>>
>> Whereas other languages are often fixed in their handling of overflow,
>> C++ is flexible - you can make your own classes to handle overflow just
>> the way you want. The language does not impose any choice on the users,
>> but provides the mechanisms to let you make whatever kinds of integers
>> you want with whatever overflow handling you want. (You can also do
>> C-style manual checks whenever you feel the need.)
>>
> You reply to where I mentioned that programmers can write their own
> trapping, (or saturating or wrapping) arithmetic using compiler intrinsics.
> Those are not part of C++ language. C++ language is as unhelpful as it
> only can. There is only undefined behavior available. How is that flexible?
> So compiler writers have attempted to at least help a bit.
I did not at all suggest that people have to use non-portable compiler
intrinsics. You /can/, if you want. And if you want a good, reusable
and efficient class, then that's what you should do - with conditional
compilation and generic fall-backs for portability.
So you want something like :
class CheckedInt32 {
private :
int32_t x_;
public :
constexpr CheckedInt32() : x_(0) {}
constexpr CheckedInt32(int32_t x) : x_(x) {}
explicit constexpr operator int32_t () { return x_; }
friend constexpr CheckedInt32 operator + (CheckedInt32 a,
CheckedInt32 b);
};
#if defined __GNUC__
constexpr CheckedInt32 operator + (CheckedInt32 a, CheckedInt32 b) {
int32_t y = 0;
if (__builtin_add_overflow(a.x_, b.x_, &y)) {
throw std::overflow_error("Overflow when adding");
}
return CheckedInt32(y);
}
#else
constexpr CheckedInt32 operator + (CheckedInt32 a, CheckedInt32 b) {
int64_t y = (int64_t) a.x_ + (int64_t) b.x_;
if ((y > INT32_MAX) || (y < INT32_MIN)) {
throw std::overflow_error("Overflow when adding");
}
return CheckedInt32(y);
}
#endif
It would be very nice to have this sort of thing as a template library
in the standard library, so that implementations could have optimal
implementations. I gather that C23 will have <stdckdint.h> with
functions/macros like "chk_add" that do this - I don't know if and when
C++ will pick it up.
So to be clear, I would like the standards to include this sort of thing
- as well as defined wrapping behaviour. But it must be in /addition/
to the "undefined behaviour" option, which must remain the default.
>
>> As another common example of undefined behaviour, let's look at
>> dereferencing invalid pointers - such as attempting to access array
>> elements outside of the array's bounds. This is UB in C and C++. On
>> bigger systems, hardware (MMU) and software (the OS) combine to give
>> near zero-overhead trapping for accesses that are far out of bounds,
>> outside the memory space of the process. This is vital for secure and
>> reliable multi-program and multi-user systems. But it could not be
>> behaviour defined or required in the language standard, because many
>> smaller systems (typically single-program devices) cannot do anything
>> like this, and even on big systems the mechanisms can vary wildly.
>>
>> For "close miss" errors, where the target address is inside the
>> processes' memory spaces, there is no general low-cost mechanism to
>> detect and prevent such invalid accesses. The language would require
>> "fat pointers" everywhere, with very different ways of dealing with
>> accesses, array slices, etc. Basically, the language would have to
>> remove the concepts of "pointer" and direct references entirely - fine
>> for slow, safe, interpreted Python but not appropriate for C or C++.
>> Leaving the behaviour undefined means tools can add checking (like
>> memory sanitizers or valgrind) for debugging, and optimise code that you
>> know is correct. Note also that there is no general way to determine if
>> an access will be a "close miss" or outside the processes' memory spaces.
>>
>> And again, you can add whatever behaviour and checks you like for your
>> own use. Put in checks manually. Make your own "array" class that has
>> bound-checked indexing by default, if that's what suits you.
>>
> For those other examples there are even no compiler intrinsics.
> Can do basically nothing but to use the skills accumulated with
> decades to help out. Again, even if to remove quarter of undefined
> behaviors the language would become simply better by that quarter.
You can't remove this class of undefined behaviour - not even a quarter
of them. The best you can do is have the compiler complain in the few
cases that it can clearly see a problem, such as when there is a
constant array index that is known to be out of bounds. But you can't
mandate that in the language standards, because it is highly dependent
on the compiler, the code, and options.
> There are no good or beneficial undefined behaviors.
We've already gone through this. Nothing good can ever come of trying
to execute something with undefined behaviour. But the fact that many
things in the languages have undefined behaviour is a good thing - for
example, without that possibility, there would be no such thing as a
pointer (since we agree that invalid memory accesses cannot, in general,
have defined behaviours).
>
>> "Undefined behaviour" is key to how C and C++ work, and what makes them
>> great languages. It is utterly essential to the philosophy of "zero
>> overhead" and not paying for things you don't use. As a C and C++
>> programmer, it is /your/ choice and /your/ responsibility to make sure
>> the code is correct, and to choose whatever level of extra checking you
>> feel appropriate to the task in hand. With C++ you can make your
>> classes to automate this as needed - UB is vital to giving you that freedom.
>>
> All people are fallible. They make mistakes with often boring stuff that
> compiler could refuse or that hardware does already trap. It is no way
> super "key feature" that those opportunities are ignored.
>
That is why it is vital that such mistakes in code are undefined
behaviour - because only then can tools add testing and trapping
behaviour to aid debugging.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2023-03-13 08:25 -0700 |
| Message-ID | <e0800e6d-fb43-4109-a15a-a42c1fc5d3ebn@googlegroups.com> |
| In reply to | #89708 |
On Monday, 13 March 2023 at 15:30:25 UTC+2, David Brown wrote: > On 12/03/2023 17:29, Öö Tiib wrote: > > On Sunday, 12 March 2023 at 12:54:57 UTC+2, David Brown wrote: > >> On 10/03/2023 17:20, Öö Tiib wrote: > >> > >>> Undefined behavior is neither obvious nor certain. Incorrectness results > >>> with program doing whatever only because rules say so. Throwing from > >>> function "void f() noexcept;" is also obviously incorrect yet C++ standard > >>> requires calling std::terminate() on that case. > >>> There are reasons why intrinsics like __builtin_saddll_overflow are > >>> there. Only that I do not want the code to call function named in Orcish > >>> and check a bool. I would like guaranteed terminate, signal or exception. > >>> > >> Even if it has not always been clear in this thread, I think we can > >> agree on quite a number of things: > >> > >> Any code that attempts to execute code with undefined behaviour, is > >> buggy. In some cases, it might work well enough for a while and then > >> fail due to later changes (such as in the anecdote about strcpy). > >> > >> Undefined behaviour which could be caught at compile/link time without > >> unreasonable compiler effort, should be caught there. > >> > >> Some kinds of undefined behaviour - bugs in the code - could be detected > >> by run-time checks, with or without hardware support. If hardware can > >> handle the checks with no overhead, that's great. If there is overhead > >> in code speed or missed optimisation, that must be balanced against the > >> benefits of catching bugs. > >> > >> (If you don't agree on these points, I hope you'll say so.) > >> > > Basically I agree just that the trend is that even the bugs that are detected > > on hardware level are ignored. That is like the effort of hardware designers > > was wasted. Instead compilers often generate code that bypasses those > > hardware checks and does something odd or even what programmers > > did expect instead. So code generation is too much balanced towards > > not catching bugs. That is pointless philosophy of unreliability. > > > >> I am of the opinion that if a language cannot define a particular > >> behaviour in a correct manner, then it should be left undefined. I see > >> no point in a language insisting on incorrect behaviour. Leaving it > >> undefined gives the implementation freedom to optimise on the assumption > >> that it does not happen when the user is looking for optimal efficiency, > >> and also to allow extra checks and debugging aids to help developers > >> find problems in their code. Defining behaviour limits that, while not > >> being able to give the programmer any useful benefits. > >> > > The integer arithmetic has been very rarely important to performance > > for very long time. It was already in nineties when people did show that > > with simpler compression algorithms uncompressing can be quicker > > than memcpy between two uncompressed buffers. Changes in integer > > arithmetic are rarely needed for performance but often for correctness. > > > That is, at best, a very narrow view - at worst it is just wrong. > > It is certainly the case that memory speeds have not increased at close > to the rate of the increase in processor speeds - for large processors. > But, again, you are missing the big picture and only considering one > type of processor. It's a different world outside of your PC. > It is becoming relatively rarely worth to write C++ for PC. Small processors tend to be quite powerful for surrounding hardware so are often idle. If these have some algebra to do then it is often floating point or if these compress, decompress or crypt something then that is done with wrapping arithmetic. In my experience. You might have different problem domain. > You are also failing to consider that the compression and decompression > relies heavily on integer arithmetic, as does all pointer arithmetic. > > It is /only/ because C and C++ compilers can generate fast code for > integer arithmetic that the compression and decompression algorithms are > fast enough to make your benchmarks run quickly. > Pointer arithmetic is also not signed integer arithmetic. So signed integer undefined behaviors do not help with those cases. > I'll happily agree that code efficiency is not important in all code. > And I am more than happy to agree that code correctness is far more > important than code efficiency. > > But I do not accept that all correct code should be made to run > inefficiently just because some code is incorrect. If you want to do > that, pick a different programming language with a different balance > between efficiency and treatment of potential errors in code - C and C++ > are not the languages for you. > Great that you agree. Note that it does not run inefficiently. There are not lot of "magic" performance boosts hidden in unreliability of signed integers. Rust for example traps in debug mode and wraps in release mode ... result is rather competitive in performance. Ada always throws and also performs not bad. > >> Let's take a couple of examples. For signed integer overflow, there are > >> two realistic possible definitions for behaviour - two's complement > >> wrapping, and trapping. (There are other possibilities, such as > >> saturation, but that's going to be inefficient on most hardware.) Some > >> languages, such as Java, use wrapping. For some simple expressions, > >> that is efficient on all realistic hardware - but for many expressions > >> it limits optimisations and is therefore less efficient. It guarantees > >> an incorrect answer in a lot of situations. And it stops tools from > >> being able to add checks and traps for bug-hunting aids, as the language > >> does not consider overflow to be an error. Thus it is often worse than > >> useless as a feature for general coding, even though it occasionally helps. > >> > >> Some languages, such as Ada, consider overflow to be a run-time error > >> that must be detected, leading to an exception or other trapping > >> behaviour. That's great for debugging, but can be very inefficient in > >> practice, even when the programmer knows the calculation cannot overflow > >> (if the compiler can /prove/ there can be no overflow, it can omit the > >> checks). And when such exceptions are part of the defined behaviour, > >> the program needs to handle them - in many cases, there is no sensible > >> choice of behaviour for the program when it sees such errors, and any > >> code paths handling them are not seriously considered or seriously tested. > >> > >> Other languages, such as Python, do not have overflow - the integer > >> types are extendable and grow as needed. That means you always get the > >> correct answer, but at such considerable run-time cost that it is not > >> appropriate for a language aimed at efficient compiled code. > >> > >> So there are pros and cons of these possible ways of handling overflow, > >> but everything other than "undefined behaviour that is assumed not to > >> happen in correct code" has a cost. For something as low-level and > >> common as integer arithmetic, any cost can quickly become significant. > >> > >> Whereas other languages are often fixed in their handling of overflow, > >> C++ is flexible - you can make your own classes to handle overflow just > >> the way you want. The language does not impose any choice on the users, > >> but provides the mechanisms to let you make whatever kinds of integers > >> you want with whatever overflow handling you want. (You can also do > >> C-style manual checks whenever you feel the need.) > >> > > You reply to where I mentioned that programmers can write their own > > trapping, (or saturating or wrapping) arithmetic using compiler intrinsics. > > Those are not part of C++ language. C++ language is as unhelpful as it > > only can. There is only undefined behavior available. How is that flexible? > > So compiler writers have attempted to at least help a bit. > I did not at all suggest that people have to use non-portable compiler > intrinsics. You /can/, if you want. And if you want a good, reusable > and efficient class, then that's what you should do - with conditional > compilation and generic fall-backs for portability. > Yes, I have helped to repair overflow bugs from such classes. These work OK. > It would be very nice to have this sort of thing as a template library > in the standard library, so that implementations could have optimal > implementations. I gather that C23 will have <stdckdint.h> with > functions/macros like "chk_add" that do this - I don't know if and when > C++ will pick it up. > I hope that quite soon. One day they should end adding (sub-bar for my usages) stuff like <valarray>, <regex> or <format>. > So to be clear, I would like the standards to include this sort of thing > - as well as defined wrapping behaviour. But it must be in /addition/ > to the "undefined behaviour" option, which must remain the default. > It is unclear to me why it must be default behavior. For me most optimizations are worth to do only in small subset of code base. And there other things like reducing copying, dynamic allocations or adding cache blocking give way more than signed integer micro-optimizations. Especially if those are compared to wrapping (that I agree is usually error). Explicit checks and branches in code can cost now but I'm sure that if like's of Ada and Rust gain more market then hardware guys will add trapping signed integers. > > > >> As another common example of undefined behaviour, let's look at > >> dereferencing invalid pointers - such as attempting to access array > >> elements outside of the array's bounds. This is UB in C and C++. On > >> bigger systems, hardware (MMU) and software (the OS) combine to give > >> near zero-overhead trapping for accesses that are far out of bounds, > >> outside the memory space of the process. This is vital for secure and > >> reliable multi-program and multi-user systems. But it could not be > >> behaviour defined or required in the language standard, because many > >> smaller systems (typically single-program devices) cannot do anything > >> like this, and even on big systems the mechanisms can vary wildly. > >> > >> For "close miss" errors, where the target address is inside the > >> processes' memory spaces, there is no general low-cost mechanism to > >> detect and prevent such invalid accesses. The language would require > >> "fat pointers" everywhere, with very different ways of dealing with > >> accesses, array slices, etc. Basically, the language would have to > >> remove the concepts of "pointer" and direct references entirely - fine > >> for slow, safe, interpreted Python but not appropriate for C or C++. > >> Leaving the behaviour undefined means tools can add checking (like > >> memory sanitizers or valgrind) for debugging, and optimise code that you > >> know is correct. Note also that there is no general way to determine if > >> an access will be a "close miss" or outside the processes' memory spaces. > >> > >> And again, you can add whatever behaviour and checks you like for your > >> own use. Put in checks manually. Make your own "array" class that has > >> bound-checked indexing by default, if that's what suits you. > >> > > For those other examples there are even no compiler intrinsics. > > Can do basically nothing but to use the skills accumulated with > > decades to help out. Again, even if to remove quarter of undefined > > behaviors the language would become simply better by that quarter. > > You can't remove this class of undefined behaviour - not even a quarter > of them. The best you can do is have the compiler complain in the few > cases that it can clearly see a problem, such as when there is a > constant array index that is known to be out of bounds. But you can't > mandate that in the language standards, because it is highly dependent > on the compiler, the code, and options. > Rust attempts to do that and in quite convincing manner. It is bit raw yet and so tricky to populate a team but it gets better all the time. > > There are no good or beneficial undefined behaviors. > > We've already gone through this. Nothing good can ever come of trying > to execute something with undefined behaviour. But the fact that many > things in the languages have undefined behaviour is a good thing - for > example, without that possibility, there would be no such thing as a > pointer (since we agree that invalid memory accesses cannot, in general, > have defined behaviours). > Raw pointer is itself of too general purpose. I prefer everything with however little more constraints like references, iterators, indexes, containers, smart pointers. These each remove undefined behaviors only by making meaningless in context operations unavailable. And that is not sole thing that those improve. > > > >> "Undefined behaviour" is key to how C and C++ work, and what makes them > >> great languages. It is utterly essential to the philosophy of "zero > >> overhead" and not paying for things you don't use. As a C and C++ > >> programmer, it is /your/ choice and /your/ responsibility to make sure > >> the code is correct, and to choose whatever level of extra checking you > >> feel appropriate to the task in hand. With C++ you can make your > >> classes to automate this as needed - UB is vital to giving you that freedom. > >> > > All people are fallible. They make mistakes with often boring stuff that > > compiler could refuse or that hardware does already trap. It is no way > > super "key feature" that those opportunities are ignored. > > > That is why it is vital that such mistakes in code are undefined > behaviour - because only then can tools add testing and trapping > behaviour to aid debugging. That does not follow. Defined error helps to debug lot better, as it is required to fail compile or run time and so can be silenced only with special options not achieved by using separate special tools.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-03-13 17:54 +0100 |
| Message-ID | <tunkg6$3rl52$1@dont-email.me> |
| In reply to | #89712 |
On 13/03/2023 16:25, Öö Tiib wrote: > On Monday, 13 March 2023 at 15:30:25 UTC+2, David Brown wrote: >> On 12/03/2023 17:29, Öö Tiib wrote: >>> On Sunday, 12 March 2023 at 12:54:57 UTC+2, David Brown wrote: >>>> On 10/03/2023 17:20, Öö Tiib wrote: >>>> >>>>> Undefined behavior is neither obvious nor certain. Incorrectness results >>>>> with program doing whatever only because rules say so. Throwing from >>>>> function "void f() noexcept;" is also obviously incorrect yet C++ standard >>>>> requires calling std::terminate() on that case. >>>>> There are reasons why intrinsics like __builtin_saddll_overflow are >>>>> there. Only that I do not want the code to call function named in Orcish >>>>> and check a bool. I would like guaranteed terminate, signal or exception. >>>>> >>>> Even if it has not always been clear in this thread, I think we can >>>> agree on quite a number of things: >>>> >>>> Any code that attempts to execute code with undefined behaviour, is >>>> buggy. In some cases, it might work well enough for a while and then >>>> fail due to later changes (such as in the anecdote about strcpy). >>>> >>>> Undefined behaviour which could be caught at compile/link time without >>>> unreasonable compiler effort, should be caught there. >>>> >>>> Some kinds of undefined behaviour - bugs in the code - could be detected >>>> by run-time checks, with or without hardware support. If hardware can >>>> handle the checks with no overhead, that's great. If there is overhead >>>> in code speed or missed optimisation, that must be balanced against the >>>> benefits of catching bugs. >>>> >>>> (If you don't agree on these points, I hope you'll say so.) >>>> >>> Basically I agree just that the trend is that even the bugs that are detected >>> on hardware level are ignored. That is like the effort of hardware designers >>> was wasted. Instead compilers often generate code that bypasses those >>> hardware checks and does something odd or even what programmers >>> did expect instead. So code generation is too much balanced towards >>> not catching bugs. That is pointless philosophy of unreliability. >>> >>>> I am of the opinion that if a language cannot define a particular >>>> behaviour in a correct manner, then it should be left undefined. I see >>>> no point in a language insisting on incorrect behaviour. Leaving it >>>> undefined gives the implementation freedom to optimise on the assumption >>>> that it does not happen when the user is looking for optimal efficiency, >>>> and also to allow extra checks and debugging aids to help developers >>>> find problems in their code. Defining behaviour limits that, while not >>>> being able to give the programmer any useful benefits. >>>> >>> The integer arithmetic has been very rarely important to performance >>> for very long time. It was already in nineties when people did show that >>> with simpler compression algorithms uncompressing can be quicker >>> than memcpy between two uncompressed buffers. Changes in integer >>> arithmetic are rarely needed for performance but often for correctness. >>> >> That is, at best, a very narrow view - at worst it is just wrong. >> >> It is certainly the case that memory speeds have not increased at close >> to the rate of the increase in processor speeds - for large processors. >> But, again, you are missing the big picture and only considering one >> type of processor. It's a different world outside of your PC. >> > It is becoming relatively rarely worth to write C++ for PC. Small > processors tend to be quite powerful for surrounding hardware so > are often idle. If these have some algebra to do then it is often floating > point or if these compress, decompress or crypt something then that > is done with wrapping arithmetic. In my experience. You might have > different problem domain. > The work done on PC's is totally and completely dominated by code written in C or C++. You will probably find that all but a couple of percent of used processor cycles is running code written in C or C++. The programmer may have written source code in C#, or Python, or Ruby, but the VM it runs on is in C or C++. The libraries that do the work in the graphics, the network, the filesystems, the game engine - it's all C and C++. I think it is a good thing that people use different languages on PC's. People can find a different balance between efficiency of the developer and efficiency at run-time, or between developer knowledge and experience and the safety of the code. Some will use low-level languages and take care to get the details right - others will use high-level languages and let the language runtime handle the details. But you could say that it is precisely because a lot of modern PC programming is done in languages other than C and C++, that it is even more important that efficiency is a high-priority in C and C++. And it is even more appropriate to expect the C and C++ programmers to be good at their jobs and not need hand-holding to get simple tasks right. So for PC's, you absolutely want to be able to conduct your integer arithmetic as fast as possible without any unnecessary checking, traps, exceptions, or other hinders in the flow. As for your comments on embedded systems, I think you are seriously misunderstanding the point when you say it is often wrapping arithmetic. If wrapping is what you need - and it is /sometimes/ right, but not often, even in cryptography - that's fine. But if it is wrong, it is wrong. It really doesn't matter here if the behaviour is defined and wrong, or undefined and wrong - except that being defined means it's harder to find the errors and efficiency might be lower. The programmer still needs to make the effort to make sure the inputs are valid for the expressions in use. And when the programmer has made the effort, any extra checks added by the compiler are a waste. (I would like C and C++ to have unsigned types that have undefined overflow behaviour, as found in the language Zig. I would not want to give up on having wrapping types too - I want both.) >> You are also failing to consider that the compression and decompression >> relies heavily on integer arithmetic, as does all pointer arithmetic. >> >> It is /only/ because C and C++ compilers can generate fast code for >> integer arithmetic that the compression and decompression algorithms are >> fast enough to make your benchmarks run quickly. >> > Pointer arithmetic is also not signed integer arithmetic. So signed > integer undefined behaviors do not help with those cases. > Pointer arithmetic is calculated with integer arithmetic semantics in C and C++, and with the same kind of instructions in implementations. But it has even more restrictions in the valid domains and it is even harder to detect overflows. "arr[i]" means "*(arr + i)", where the expression "arr + i" overflows on any result outside the array. Everything that applies to signed integer overflow applies even more so to pointer arithmetic. >> I'll happily agree that code efficiency is not important in all code. >> And I am more than happy to agree that code correctness is far more >> important than code efficiency. >> >> But I do not accept that all correct code should be made to run >> inefficiently just because some code is incorrect. If you want to do >> that, pick a different programming language with a different balance >> between efficiency and treatment of potential errors in code - C and C++ >> are not the languages for you. >> > Great that you agree. Note that it does not run inefficiently. There are > not lot of "magic" performance boosts hidden in unreliability of signed > integers. Rust for example traps in debug mode and wraps in release > mode ... result is rather competitive in performance. Ada always throws > and also performs not bad. > Rust and Ada perform reasonably, but not on a par with C and C++. People spend vast amounts on buying a processor that is 20% faster than mainstream alternatives - they do not want to run their code 50% slower. Your thoughts here seems to be based on the idea that code just does a bit of integer arithmetic every now and again, and the cpu is probably waiting for slow main memory anyway. That's true for some code. It is very far from true for other code. On small systems, you are rarely waiting for memory, and individual cycles count. You don't enable exceptions in C++, you don't stop with error messages - you have nowhere to show an error message. Even if you do get an error, what are you going to do about it? Recall all the microwave ovens or oil valve controllers you've made? You write the code correctly so that it doesn't overflow, and doesn't stop - or you are looking for a new job. Extra checking just means bigger and more expensive hardware to do the same job, taking extra power from your battery life. And if you look at PC's and big processors, you might have noticed a trend in the last decades of more and more vector processing. While some of that is for floating point vectors, doesn't it still give you a clue that people /do/ care about integer arithmetic performance? >>>> Whereas other languages are often fixed in their handling of overflow, >>>> C++ is flexible - you can make your own classes to handle overflow just >>>> the way you want. The language does not impose any choice on the users, >>>> but provides the mechanisms to let you make whatever kinds of integers >>>> you want with whatever overflow handling you want. (You can also do >>>> C-style manual checks whenever you feel the need.) >>>> >>> You reply to where I mentioned that programmers can write their own >>> trapping, (or saturating or wrapping) arithmetic using compiler intrinsics. >>> Those are not part of C++ language. C++ language is as unhelpful as it >>> only can. There is only undefined behavior available. How is that flexible? >>> So compiler writers have attempted to at least help a bit. >> I did not at all suggest that people have to use non-portable compiler >> intrinsics. You /can/, if you want. And if you want a good, reusable >> and efficient class, then that's what you should do - with conditional >> compilation and generic fall-backs for portability. >> > Yes, I have helped to repair overflow bugs from such classes. These > work OK. That's the great thing about C++. Get it working right once, and use it repeatedly. > >> It would be very nice to have this sort of thing as a template library >> in the standard library, so that implementations could have optimal >> implementations. I gather that C23 will have <stdckdint.h> with >> functions/macros like "chk_add" that do this - I don't know if and when >> C++ will pick it up. >> > I hope that quite soon. One day they should end adding (sub-bar > for my usages) stuff like <valarray>, <regex> or <format>. > Different people have different needs. There's lots in the standard library that is useless to me - but I realise it is useful to /some/ people. >> So to be clear, I would like the standards to include this sort of thing >> - as well as defined wrapping behaviour. But it must be in /addition/ >> to the "undefined behaviour" option, which must remain the default. >> > It is unclear to me why it must be default behavior. For me most > optimizations are worth to do only in small subset of code base. > And there other things like reducing copying, dynamic allocations or > adding cache blocking give way more than signed integer > micro-optimizations. Especially if those are compared to wrapping > (that I agree is usually error). Explicit checks and branches in code > can cost now but I'm sure that if like's of Ada and Rust gain more > market then hardware guys will add trapping signed integers. > Just to be clear here - gcc (and presumably other compilers) have had options for defined signed integer overflow for decades. You can choose wrapping (-fwrapv) or trapping (-ftrapv). These are very rarely used in practice - people either don't know about such things (and those programmers would be unlikely to do a decent job of handling run-time errors even if were the default), or they don't want such features. gcc developers have long since realised that trying to make relatively efficient checked integer arithmetic (as -ftrapv did) was pretty much useless. It had significant overhead, was inconsistent, gave little useful feedback, and only handled one small class of common errors. Instead, they recommend more complete debugging tools such as sanitizers that check much more and give more useful debugging feedback. Ada is virtually dead as a language. Rust is a fad - the benefits you get from re-writing C code in Rust can be achieved almost entirely by re-writing the C code in decent modern C and using modern C development tools. (Still, if it is easier to make people fix bugs by re-writing in Rust than getting them to re-write in good C, the end result is fewer bugs.) And if your re-write is good modern C++, even better. Why bother with code analysis "borrow checker" tools with Rust when you can write the code in C++ in a way that makes you sure you don't have memory usage failures? I suppose the best you can say is that Rust makes it marginally harder to write incorrect code, for some kinds of error. >> You can't remove this class of undefined behaviour - not even a quarter >> of them. The best you can do is have the compiler complain in the few >> cases that it can clearly see a problem, such as when there is a >> constant array index that is known to be out of bounds. But you can't >> mandate that in the language standards, because it is highly dependent >> on the compiler, the code, and options. >> > Rust attempts to do that and in quite convincing manner. It is bit raw > yet and so tricky to populate a team but it gets better all the time. > You've swallowed the cool-aid. Rust, with all its bells and whistles used correctly, is a big step up from malloc/free, and even new/delete. But if you are happy with the overhead then you can replace you arrays with std::vector and you don't need a half-made borrow checker to be sure you are leak-free. >>> >> That is why it is vital that such mistakes in code are undefined >> behaviour - because only then can tools add testing and trapping >> behaviour to aid debugging. > > That does not follow. Defined error helps to debug lot better, as it > is required to fail compile or run time and so can be silenced only > with special options not achieved by using separate special tools. I can only re-state my points in a limited number of ways. Either you understand what I am saying, or you don't.
[toc] | [prev] | [next] | [standalone]
Page 6 of 8 — ← Prev page 1 2 3 4 5 [6] 7 8 Next page →
Back to top | Article view | comp.lang.c++
csiph-web