New Safe C++ Proposal

Pages: 123
The following is from the knowledge and expertise of a self-taught programming hobbyist:

The more problems in code that can be caught at compile time is a good thing, even if it requires a bit of safety scaffolding to achieve.

An example....std::format before P2216R3 (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2216r3.html)
A malformed formatting string compiled just fine without problems, at least with VS2019/2022. To catch any possible boo-boos using try/catch blocks was required. Or watch the program crash. Requiring debugging to discover why and where everything fell down and went *BOOM!*

After this proposal was applied to the C++ standard now a malformed formatting string won't compile. No need for exception handling, at least for formatting.

The few examples of C++ Safety scaffolding I see in the proposal is somewhat akin to the Desktop WinAPI SAL notation. https://learn.microsoft.com/en-us/cpp/code-quality/understanding-sal?view=msvc-170

M'ok, someone is not required to use SAL to document WinAPI code, if it is missing the MSVC compiler merely whinges and still creates an executable.

The C++ Safety proposal merely ups the checking for potential run-time problems at what appears to be compile-time, reporting hazards before they are released into the wild. Using it won't likely be required, but like the C++ Core Guidelines it could be a damned good recommendation for creating more robust code with minimal fuss.

At least that is my take on what I read is being proposed. I could be wrong. ¯\_(ツ)_/¯

I'm comfortable with using SAL for WinAPI code, from what I've seen of how to use C++ Safety it wouldn't be a huge burden to use going forward after adoption. Every C++ standard IMO changes the language and helps make it better for the most part.

Even the back and forth method for lambda capture of the this pointer between C++ stdlib versions.

cppreference wrote:
1
2
3
4
5
6
7
8
9
10
struct S2 { void f(int i); };
void S2::f(int i)
{
    [=] {};        // OK: by-copy capture default
    [=, &i] {};    // OK: by-copy capture, except i is captured by reference
    [=, *this] {}; // until C++17: Error: invalid syntax
                   // since C++17: OK: captures the enclosing S2 by copy
    [=, this] {};  // until C++20: Error: this when = is the default
                   // since C++20: OK, same as [=]
}

(Yes, I do understand the difference between *this and this, m'ok? And the reasoning behind the usage difference. I merely find it interesting lambda capture of this changed between standards.)

*Back to my lounge chair and pop-corn....*
Like I said, it's the type of nonsense dynamic language fanatics say. Formal checking is much stronger than testing. Testing should only be enhancing it, not replacing it.

The reason for testing plenty before implementation in this case is when implementing wrong code would be devastating. So you're testing to make sure your code works, not necessarily to make sure you haven't created UB.

If you're code alters the data you're using and its too large to have a copy, then the code better work before implementation.

While UB is its own class of errors, it's rarely sneaky. If you have an off by one error, for example, then your expected output will not match the output. Use vectors and safe pointers, then these issues are mostly impossible anyway.

Dynamic languages have no checking at compile-time, just waits for things to go wrong. This makes testing not only necessary, but you better test every nook and cranny of your code.


The C++ Safety proposal merely ups the checking for potential run-time problems at what appears to be compile-time

That would be "fine", but would not be enough to eliminate most UB the way Rust apparently has.
it's rarely sneaky. If you have an off by one error, for example, then your expected output will not match the output
You're wrong. It is often sneaky. It is quite easy to have incorrect code whose behavior becomes undefined only under certain conditions, or code that contains UB from the start, but due to the way the compiler has laid out memory does not trigger any failures and just sits there waiting to be exploited, or (most annoyingly) code that fails obviously but rarely and unpredictably.
You can't unit test against UB because it is UB. All behaviors, including returning correct results, are permissible. Even if you had 100% coverage you may not detect all existing UB in your program, due to statefulness and non-determinism.

I very much believe these safety issues are an existential threat to C++. If they're not addressed people may simply abandon the language. I love the language, and even I think it's foolish to code an Internet-facing service in it.
Registered users can post here. Sign in or register to post.
Pages: 123