C++ float-to-int conversion can be undefined behavior

(kttnr.net)

13 points | by Quentak a day ago ago

16 comments

  • inigyou 11 hours ago ago

    Undefined behavior was, in most cases, intended to encompass a point where different implementations behaved in reasonable ways. In case of overflow, some implementations wrapped, some saturated, some threw an exception, some jumped to an interrupt handler, and some returned 0. They made it undefined intending to encompass all of these. Notice they are all fairly reasonable (except for returning 0).

    Later, stupid compiler writers decided that since the wording allows anything to happen, it also allows time travel or memory corruption. These are not reasonable, but they are allowed by the wording of the standard.

    The standard should be fixed to say it returns an undefined value or activates an error handling mechanism. Nobody could argue that time travel is an error handling mechanism.

    • aw1621107 11 hours ago ago

      > They made it undefined intending to encompass all of these.

      Why wouldn't implementation-defined behavior suffice in this case?

      • inigyou 11 hours ago ago

        IB means the implementation has to fully document what it does. Evidently they didn't want to impose that requirement.

        • aw1621107 11 hours ago ago

          There's always unspecified behavior if documentation is considered to be too onerous.

        • UncleMeat 10 hours ago ago

          It also means that the behavior needs to be stable across time and that tools cannot report this behavior as a bug.

  • Panzerschrek 18 hours ago ago

    A good example of C++ bizarre design decisions. The exact handing of float<->int conversions should use implementation-defined behavior instead, defining some cases to be UB just adds more traps with little to no performance benefits.

    The same is true for bit-shifts greater than type bit size and negative bit-shifts.

    • Frieren 17 hours ago ago

      > bizarre design decisions

      They are not bizarre but a good compromise between consistency and optimization for any possible existing and future CPU architecture.

      What the author correctly points out to is that GSL implementation does not remove that undefined behaviour as it lacks the proper checks. And that is the problem as it does not fulfill its own documented guarantees.

      tldr; C++ is just fine. The implementation in the library is wrong.

      • Panzerschrek 17 hours ago ago

        > C++ is just fine

        No it isn't. Using undefined behavior for things which can be implementation-defined behavior instead is harmful. It creates more space for bugs and security vulnerabilities.

        • Frieren 16 hours ago ago

          C++ was designed as an universal way of writing low level system code. It has some abstractions above C, but still allowing for all kinds of optimizations. (Think using a class vs a template, similar abstraction different impact).

          To use C++ to code user programs is the actual mistake.

          Think about assembly. Should assembly also be safe in all calls? That will make everything slower, and consume way more energy. Will you blame assembly if people used it to create a phone app and it had memory leaks? Or will you blame the developer for using assembly in the first place?

          C++ is a tool designed for a range of purposes. There is a push to make it an universal language that makes everything well. But engineering is about making compromises.

          For your use, C++ may be the wrong language. I do not disagree with you. But maybe you should be using another language instead. Or we should create a new language that fills the sweet spot that C++ covers, and then evolve C++ to be the safe language that you want. One way or another, it is a compromise.

          • atiedebee 14 hours ago ago

            I thought C++ was designed to fit all sorts of applications. There is many GUI libraries for C++ for example, and the language has all the capabilities to add abstractions for making these sorts of libraries easy to work with. I think you could argue that C was made for low level code, since the working group seems to be focussing on making the core of the language more usable instead of allowing for abstractions that make libraries easier to work with (I think we can all agree that the C interface of gtk is not that great to work with, though I do commend their efforts).

            Sorry for rambling so much, I hope I got my point across.

            • inigyou 11 hours ago ago

              C was made as more portable assembly, and C++ was made to add lots of features to C.

            • imtringued 13 hours ago ago

              Apparently you thought wrong and should stop using C++.

        • UncleMeat 10 hours ago ago

          What is an appropriate behavior for casting inf or nan to an integer?

      • 3836293648 12 hours ago ago

        No? That would mean implementation defined, not undefined.

      • imtringued 13 hours ago ago

        They are bizarre, because C developer culture isn't known for doing what is necessary to prove the absence of UB and memory safety problems.

        It's all up to the programmer who obviously won't invest the time because that would ruin the development velocity.

        • inigyou 11 hours ago ago

          If UB was limited to dereferencing freed memory and so on, it would be better.