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


Groups > comp.lang.c++ > #89514 > unrolled thread

"C++ on the Move" by Darryl K. Taft

Started byLynn McGuire <lynnmcguire5@gmail.com>
First post2023-03-07 15:38 -0600
Last post2023-04-06 00:42 -0700
Articles 20 on this page of 146 — 22 participants

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


Contents

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


#89750

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-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]


#89752

FromMuttley@dastardlyhq.com
Date2023-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]


#89632

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-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]


#89635

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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]


#89626

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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]


#89629

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-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]


#89636

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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]


#89640

FromÖö Tiib <ootiib@hot.ee>
Date2023-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]


#89644

Fromkalevi@kolttonen.fi (Kalevi Kolttonen)
Date2023-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]


#89668

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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]


#89675

FromÖö Tiib <ootiib@hot.ee>
Date2023-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]


#89677

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-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]


#89679

FromÖö Tiib <ootiib@hot.ee>
Date2023-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]


#89709

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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]


#89714

FromÖö Tiib <ootiib@hot.ee>
Date2023-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]


#89688

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-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]


#89697

FromÖö Tiib <ootiib@hot.ee>
Date2023-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]


#89708

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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]


#89712

FromÖö Tiib <ootiib@hot.ee>
Date2023-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]


#89717

FromDavid Brown <david.brown@hesbynett.no>
Date2023-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