• "How we used C++20 to eliminate an entire class of runtime bugs" by Cam

    From Lynn McGuire@21:1/5 to All on Tue Jan 18 19:24:21 2022
    "How we used C++20 to eliminate an entire class of runtime bugs" by
    Cameron DaCamara

    https://devblogs.microsoft.com/cppblog/how-we-used-cpp20-to-eliminate-an-entire-class-of-runtime-bugs/

    "C++20 is here and has been supported in MSVC since 16.11, but today’s
    post is not about how you can use it, but rather how we used it to
    effectively eliminate an entire class of runtime bugs by hoisting a
    check into compile-time. Let’s get right into it!"

    Lynn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From wij@21:1/5 to Lynn McGuire on Thu Jan 20 02:37:16 2022
    On Wednesday, 19 January 2022 at 09:24:37 UTC+8, Lynn McGuire wrote:
    "How we used C++20 to eliminate an entire class of runtime bugs" by
    Cameron DaCamara

    https://devblogs.microsoft.com/cppblog/how-we-used-cpp20-to-eliminate-an-entire-class-of-runtime-bugs/

    "C++20 is here and has been supported in MSVC since 16.11, but today’s post is not about how you can use it, but rather how we used it to effectively eliminate an entire class of runtime bugs by hoisting a
    check into compile-time. Let’s get right into it!"

    Lynn

    The idea of using errno for error-handling (mandatory) had developed nearly 20 years ago and very successful. https://sourceforge.net/projects/cscall/files/latest/download
    It is about error checking, or inline test (programmers don't like this term). Coding syntax in this preliminary level may be too early (C++ is already burdensome
    , mostly developed from enthusiasm, ideal and insufficient experiences. The result
    might just be adding burdens, not 'feature', years latter).
    Hope the language developer may realize the issue of error-handling is the foundation of robust and efficient programs rather than syntax sugars. (Exception is not suitable for error-handling)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Juha Nieminen@21:1/5 to wij on Thu Jan 20 11:43:11 2022
    wij <wyniijj@gmail.com> wrote:
    The idea of using errno for error-handling (mandatory) had developed
    nearly 20 years ago and very successful.

    'errno' alone may not be enough for error handling because sometimes you
    want or need more details about the error.

    Also, while not a show-stopper, 'errno' is easy to use wrong. Consider
    how easy it is to do something like this:

    if(!someFunction())
    std::cerr << "Error calling someFunction(): " << std::strerror(errno);

    What's wrong with that? The fact that it's at least theoretically possible
    that that first operator<<() may change the value of errno (if it itself encounters some kind of error), in which case it's going to print the
    wrong error message.

    (This might be the reason for those infamous and hilarious
    "Error: No error" messages seen sometimes. It's not that there was no
    error, but that 'errno' (or whatever the program uses) was changed
    in between the actual error and showing the message.)

    (Sure, the proper way to handle this is to take the value of errno into
    a variable immediately after the function call, but consider how easy
    it's to do mistakes like the one above.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Muttley@dastardlyhq.com@21:1/5 to Juha Nieminen on Thu Jan 20 16:14:03 2022
    On Thu, 20 Jan 2022 11:43:11 -0000 (UTC)
    Juha Nieminen <nospam@thanks.invalid> wrote:
    wij <wyniijj@gmail.com> wrote:
    The idea of using errno for error-handling (mandatory) had developed
    nearly 20 years ago and very successful.

    'errno' alone may not be enough for error handling because sometimes you
    want or need more details about the error.

    Also, while not a show-stopper, 'errno' is easy to use wrong. Consider
    how easy it is to do something like this:

    if(!someFunction())
    std::cerr << "Error calling someFunction(): " << std::strerror(errno);

    What's wrong with that? The fact that it's at least theoretically possible >that that first operator<<() may change the value of errno (if it itself >encounters some kind of error), in which case it's going to print the
    wrong error message.

    (This might be the reason for those infamous and hilarious
    "Error: No error" messages seen sometimes. It's not that there was no
    error, but that 'errno' (or whatever the program uses) was changed
    in between the actual error and showing the message.)

    AFAIK the standard C library only sets errno if an error occurs. It never resets it to zero if there was no error. One would assume the C++ standard libraries behave the same way so "Error: no error" would only occur if the program has mistakenly seen a return value as a system error which would
    set errno when it might actually be a higher level error which doesn't.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Juha Nieminen on Thu Jan 20 11:57:57 2022
    On 1/20/22 6:43 AM, Juha Nieminen wrote:
    ...
    (This might be the reason for those infamous and hilarious
    "Error: No error" messages seen sometimes. It's not that there was no
    error, but that 'errno' (or whatever the program uses) was changed
    in between the actual error and showing the message.)

    When I've been in a position to check such things, I've usually found
    that they are the result of calling perror() without first checking
    whether errno was non-zero. When you use perror(), you should check to
    make sure under which circumstances the previously called function sets
    errno. Some things that are considered errors from the point of view of
    the developer do not actually result in errno being set.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From wij@21:1/5 to Juha Nieminen on Thu Jan 20 09:06:36 2022
    On Thursday, 20 January 2022 at 19:43:27 UTC+8, Juha Nieminen wrote:
    wij <wyn...@gmail.com> wrote:
    The idea of using errno for error-handling (mandatory) had developed
    nearly 20 years ago and very successful.
    'errno' alone may not be enough for error handling because sometimes you
    want or need more details about the error.

    Also, while not a show-stopper, 'errno' is easy to use wrong. Consider
    how easy it is to do something like this:

    if(!someFunction())
    std::cerr << "Error calling someFunction(): " << std::strerror(errno);

    What's wrong with that? The fact that it's at least theoretically possible that that first operator<<() may change the value of errno (if it itself encounters some kind of error), in which case it's going to print the
    wrong error message.

    (This might be the reason for those infamous and hilarious
    "Error: No error" messages seen sometimes. It's not that there was no
    error, but that 'errno' (or whatever the program uses) was changed
    in between the actual error and showing the message.)

    (Sure, the proper way to handle this is to take the value of errno into
    a variable immediately after the function call, but consider how easy
    it's to do mistakes like the one above.)

    What programs need is a way to branch, errno is one basic way to do this.
    I use class Errno that contains only one int data member.
    class Errno {
    int m_errno;
    public:
    constexpr Errno();
    constexpr Errno(const Errno&);
    ...
    };

    My experience of using class Errno says errno (thread-local variable) could be an option if such impl. could be faster(and smaller).

    I did not recommend my implement but two points (debating such an issue might
    be unnecessarily long and fruitless).
    1. Make error checking mandatory
    2. Use __FILE__, __LINE__ to mark WHERE error detected.

    As I know, no programming language treats error-testing an essential part.
    Most programmers don't like to use and see error-testing(or handling) codes for each function call. But I found no way to escape, and my experience showed that explicit testing for errors and handling it in the end is 'efficient', at least for programmer's time (and thus money as well).
    Others are implementation problems.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Muttley@dastardlyhq.com on Thu Jan 20 12:22:46 2022
    On 1/20/22 11:14 AM, Muttley@dastardlyhq.com wrote:
    On Thu, 20 Jan 2022 11:43:11 -0000 (UTC)
    Juha Nieminen <nospam@thanks.invalid> wrote:
    ...
    (This might be the reason for those infamous and hilarious
    "Error: No error" messages seen sometimes. It's not that there was no
    error, but that 'errno' (or whatever the program uses) was changed
    in between the actual error and showing the message.)

    AFAIK the standard C library only sets errno if an error occurs.

    Oddly enough, that's not the case:

    "The value of errno in the initial thread is zero at program startup
    (the initial value of errno in other threads is an indeterminate value),
    but is never set to zero by any library function. 218) The value of
    errno may be set to nonzero by a library function call whether or not
    there is an error, provided the use of errno is not documented in the description of the function in this document." (C standard 7.5p3).

    Implicit in that statement is the fact that "provided the use of errno
    is ... documented in the description of the function in this document.",
    then that function may only use errno as specified by that documentation.

    ... It never
    resets it to zero if there was no error.

    As specified above, it never sets it to zero at all; that occurs only at program startup, and only for the initial thread.

    ... One would assume the C++ standard
    libraries behave the same way so "Error: no error" would only occur if the program has mistakenly seen a return value as a system error which would
    set errno when it might actually be a higher level error which doesn't.

    The C++ standard prohibits the routines specified in <system_error>,
    from changing the value of errno (19.5p2). Otherwise, it never says
    anything to either mandate or prohibit changing errno. I would hope that
    what the C standard says about the use of errno by the C standard
    library can, by extension, be applied to the rest of the C++ standard
    library, but there's nothing that says so explicitly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to Lynn McGuire on Thu Jan 20 09:35:44 2022
    On 1/18/2022 5:24 PM, Lynn McGuire wrote:
    "How we used C++20 to eliminate an entire class of runtime bugs" by
    Cameron DaCamara

    https://devblogs.microsoft.com/cppblog/how-we-used-cpp20-to-eliminate-an-entire-class-of-runtime-bugs/


    "C++20 is here and has been supported in MSVC since 16.11, but today’s
    post is not about how you can use it, but rather how we used it to effectively eliminate an entire class of runtime bugs by hoisting a
    check into compile-time. Let’s get right into it!"


    What it basically boils down to is that C++20's `consteval` triggers a
    hard error for non-compile-time evaluations, as opposed to `constexpr`,
    which silently opted for run-time evaluation.

    --
    Best regards,
    Andrey Tarasevich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to wij on Thu Jan 20 17:14:53 2022
    wij <wyniijj@gmail.com> writes:

    As I know, no programming language treats error-testing an essential
    part.

    You might want to take a look at Icon. It makes extensive (and very
    effective) use of the success and failure of even the most basic
    operations forstructuring the code.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ian Collins@21:1/5 to wij on Fri Jan 21 08:50:08 2022
    On 20/01/2022 23:37, wij wrote:
    On Wednesday, 19 January 2022 at 09:24:37 UTC+8, Lynn McGuire wrote:
    "How we used C++20 to eliminate an entire class of runtime bugs" by
    Cameron DaCamara

    https://devblogs.microsoft.com/cppblog/how-we-used-cpp20-to-eliminate-an-entire-class-of-runtime-bugs/

    "C++20 is here and has been supported in MSVC since 16.11, but today’s
    post is not about how you can use it, but rather how we used it to
    effectively eliminate an entire class of runtime bugs by hoisting a
    check into compile-time. Let’s get right into it!"

    Lynn

    The idea of using errno for error-handling (mandatory) had developed nearly 20
    years ago and very successful. https://sourceforge.net/projects/cscall/files/latest/download
    It is about error checking, or inline test (programmers don't like this term).
    Coding syntax in this preliminary level may be too early (C++ is already burdensome
    , mostly developed from enthusiasm, ideal and insufficient experiences. The result
    might just be adding burdens, not 'feature', years latter).
    Hope the language developer may realize the issue of error-handling is the foundation of robust and efficient programs rather than syntax sugars. (Exception is not suitable for error-handling)

    So it's better to pick up the error at compile time, isn't it?

    The gcc and clang compilers have something similar for printf like
    logging with __attribute__ ((format (printf, FORMAT_ARG, VARG_BEGIN)))
    which has most likely saved many a run time error in similar situations.

    --
    Ian.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard@21:1/5 to All on Thu Jan 20 22:19:15 2022
    [Please do not mail me a copy of your followup]

    Lynn McGuire <lynnmcguire5@gmail.com> spake the secret code <ss7p85$p00$2@dont-email.me> thusly:

    "How we used C++20 to eliminate an entire class of runtime bugs" by
    Cameron DaCamara

    https://devblogs.microsoft.com/cppblog/how-we-used-cpp20-to-eliminate-an-entire-class-of-runtime-bugs/

    Nice success story!
    --
    "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
    The Terminals Wiki <http://terminals-wiki.org>
    The Computer Graphics Museum <http://computergraphicsmuseum.org>
    Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bonita Montero@21:1/5 to All on Fri Jan 21 10:00:38 2022
    Am 20.01.2022 um 18:35 schrieb Andrey Tarasevich:


    What it basically boils down to is that C++20's `consteval` triggers a
    hard error for non-compile-time evaluations, as opposed to `constexpr`,
    which silently opted for run-time evaluation.

    "if constexpr( )" is always compile-time evaluated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Juha Nieminen@21:1/5 to Bonita Montero on Fri Jan 21 09:03:03 2022
    Bonita Montero <Bonita.Montero@gmail.com> wrote:
    Am 20.01.2022 um 18:35 schrieb Andrey Tarasevich:
    What it basically boils down to is that C++20's `consteval` triggers a
    hard error for non-compile-time evaluations, as opposed to `constexpr`,
    which silently opted for run-time evaluation.

    "if constexpr( )" is always compile-time evaluated.

    'if constexpr' is not really a constexpr construct. It simply reuses the keyword.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bonita Montero@21:1/5 to All on Fri Jan 21 12:51:17 2022
    Am 21.01.2022 um 10:03 schrieb Juha Nieminen:
    Bonita Montero <Bonita.Montero@gmail.com> wrote:
    Am 20.01.2022 um 18:35 schrieb Andrey Tarasevich:
    What it basically boils down to is that C++20's `consteval` triggers a
    hard error for non-compile-time evaluations, as opposed to `constexpr`,
    which silently opted for run-time evaluation.

    "if constexpr( )" is always compile-time evaluated.

    'if constexpr' is not really a constexpr construct. ...

    Of course, the expression has to be compile-time evaluated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to Bonita Montero on Fri Jan 21 10:19:10 2022
    On 1/21/2022 1:00 AM, Bonita Montero wrote:
    Am 20.01.2022 um 18:35 schrieb Andrey Tarasevich:


    What it basically boils down to is that C++20's `consteval` triggers a
    hard error for non-compile-time evaluations, as opposed to
    `constexpr`, which silently opted for run-time evaluation.

    "if constexpr( )" is always compile-time evaluated.

    `if constexpr` can be used to test compile-time nature of an expression,
    but it can only be done "from the outside" of that expression. I don't immediately see how would one go about using `if constexpr` for function argument verification, especially considering that that verification has
    to be injected after template argument deduction.

    In order to achieve that injection they used a well-known technique,
    which is as old as the world itself. They implemented an intermediate pass-through `Checker` class, which performs the necessary checks in its constructor. Nothing new here.

    However, previously we would only be able generate run-time errors
    (assertion failures) from inside that constructor. That's how this
    technique has been used for ages.

    They show that now, by declaring that constructor as `consteval`, one
    can also generate compile-time errors (!) from inside that constructor.

    Of course, by doing so one's restricting oneself to compile-time
    arguments exclusively. But apparently in their application they don't
    mind that. And, if I'm mot mistaken, one can get the best of both worlds
    by branching on `if (std::is_constant_evaluated)`/`if consteval`.

    --
    Best regards,
    Andrey Tarasevich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bonita Montero@21:1/5 to All on Fri Jan 21 19:51:28 2022
    Am 21.01.2022 um 19:19 schrieb Andrey Tarasevich:
    On 1/21/2022 1:00 AM, Bonita Montero wrote:
    Am 20.01.2022 um 18:35 schrieb Andrey Tarasevich:


    What it basically boils down to is that C++20's `consteval` triggers
    a hard error for non-compile-time evaluations, as opposed to
    `constexpr`, which silently opted for run-time evaluation.

    "if constexpr( )" is always compile-time evaluated.

    `if constexpr` can be used to test compile-time nature of an expression,
    but it can only be done "from the outside" of that expression. I don't immediately see how would one go about using `if constexpr` for function argument verification, especially considering that that verification has
    to be injected after template argument deduction.

    In order to achieve that injection they used a well-known technique,
    which is as old as the world itself. They implemented an intermediate pass-through `Checker` class, which performs the necessary checks in its constructor. Nothing new here.

    However, previously we would only be able generate run-time errors
    (assertion failures) from inside that constructor. That's how this
    technique has been used for ages.

    They show that now, by declaring that constructor as `consteval`, one
    can also generate compile-time errors (!) from inside that constructor.

    Of course, by doing so one's restricting oneself to compile-time
    arguments exclusively. But apparently in their application they don't
    mind that. And, if I'm mot mistaken, one can get the best of both worlds
    by branching on `if (std::is_constant_evaluated)`/`if consteval`.

    You can virtually even check parameters with it:

    template<bool B>
    void f( bool_constabt<B> x )
    {
    if constexpr( B )
    ...
    }

    I use it very often for templated parameters, sometimes
    to check their type-properties, f.e. if they're integral.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to Bonita Montero on Fri Jan 21 12:03:39 2022
    On 1/21/2022 10:51 AM, Bonita Montero wrote:
    Am 21.01.2022 um 19:19 schrieb Andrey Tarasevich:
    On 1/21/2022 1:00 AM, Bonita Montero wrote:
    Am 20.01.2022 um 18:35 schrieb Andrey Tarasevich:


    What it basically boils down to is that C++20's `consteval` triggers
    a hard error for non-compile-time evaluations, as opposed to
    `constexpr`, which silently opted for run-time evaluation.

    "if constexpr( )" is always compile-time evaluated.

    `if constexpr` can be used to test compile-time nature of an
    expression, but it can only be done "from the outside" of that
    expression. I don't immediately see how would one go about using `if
    constexpr` for function argument verification, especially considering
    that that verification has to be injected after template argument
    deduction.

    In order to achieve that injection they used a well-known technique,
    which is as old as the world itself. They implemented an intermediate
    pass-through `Checker` class, which performs the necessary checks in
    its constructor. Nothing new here.

    However, previously we would only be able generate run-time errors
    (assertion failures) from inside that constructor. That's how this
    technique has been used for ages.

    They show that now, by declaring that constructor as `consteval`, one
    can also generate compile-time errors (!) from inside that constructor.

    Of course, by doing so one's restricting oneself to compile-time
    arguments exclusively. But apparently in their application they don't
    mind that. And, if I'm mot mistaken, one can get the best of both
    worlds by branching on `if (std::is_constant_evaluated)`/`if consteval`.

    You can virtually even check parameters with it:

    template<bool B>
    void f( bool_constabt<B> x )
    {
        if constexpr( B )
            ...
    }

    I use it very often for templated parameters, sometimes
    to check their type-properties, f.e. if they're integral.

    You are checking a template argument - an entity that is inherently compile-time. "There is no renown in that." Many techniques are
    available for checking template arguments at compile time even in C++98.

    Meanwhile, they want to check regular function arguments (!) at compile
    time (under assumption that they are supplied with compile-time
    arguments, of course). That is a wholly different story.

    And they also want to be able to check template arguments based on such
    regular function arguments.

    E.g.

    #include <string_view>
    #include <type_traits>

    template <typename T>
    struct Checker {
    consteval Checker(const char* fmt)
    {
    if (fmt == std::string_view{ "int" } &&
    std::is_same_v<T, int>)
    return;

    if (fmt == std::string_view{ "double" } &&
    std::is_same_v<T, double>)
    return;

    throw;
    }
    };

    template <typename T>
    void fmt(std::type_identity_t<Checker<T>> checked, T) {}

    int main()
    {
    fmt("int", 42); // OK
    fmt("double", 1.23); // OK
    fmt("int", "foo"); // Compile error
    }

    --
    Best regards,
    Andrey Tarasevich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)