New Safe C++ Proposal

Pages: 123456
You'd be surprised. It's not uncommon for someone to find themselves trying to solve a problem while not knowing that they don't know what they're doing.

Yes, but obviously this can lead to all sorts of issues, UB not being the greatest threat. All sorts of user-input attacks are a direct consequence of such mistakes/not knowing what you're doing. UB is likely caught by a modern OS with no damage done, while an input attack is likely to go completely unnoticed until the damage is spotted.

I think there's an even better practice: don't use a language that can get you owned when processing untrusted input

So never use mySQL..

It would be highly unusual for a tokenizer to do any but the most rudimentary of sanitizations

Only the tokenizer would be able to track such a malicious attempt, as it could track oddities, such as how many parenthesis in a row it was receiving. It can impose a limit to the size of the input and other logical restrictions that couldn't be easily (or at least ideally since it would involve going through all the data you already went through) implemented elsewhere.

The only other method would be keeping track of the depth of your recursive calls. Even then, you'd end up guessing how deep you can go before overflowing.

It's not like C++ doesn't have features that will forbid you from screwing up.

Which has been my point the whole time. And if stack overflow becomes defined behavior, that's good (I'm not sure what effect that would have to performance, but I assume small).
Last edited on
UB is likely caught by a modern OS with no damage done, while an input attack is likely to go completely unnoticed until the damage is spotted.
LOL, what are you saying? Vulnerabilities are precisely caused by UB.

So never use mySQL..
Never use MySQL because it's owned by Oracle.
SQL servers don't take untrusted input. They have logins.

Only the tokenizer would be able to track such a malicious attempt, as it could track oddities, such as how many parenthesis in a row it was receiving. It can impose a limit to the size of the input and other logical restrictions that couldn't be easily
None of that is within the purview of a tokenizer. Like I said, it's a simple conversion function. It shouldn't concern itself with anything other than converting sequences of characters into sequences of tokens.

Which has been my point the whole time.
You point the whole has been that you don't want to be prohibited from screwing up. You literally said "not saying don't add safer options, just don't prevent me from shooting myself in the foot".
LOL, what are you saying? Vulnerabilities are precisely caused by UB

Sorry, I meant stack overflow will be caught with no damage done.

SQL servers don't take untrusted input. They have logins.

They don't take input from untrusted sources. It's up to the user to make sure the input is safe. SQL will happily delete everything if malicious input tells it to do so.

It shouldn't concern itself with anything other than converting sequences of characters into sequences of tokens.

Depends on the programmer, I would certainly put it there. It would be completely inefficient to add checking anywhere else, and there's a lot of checks you may want to do.

You point the whole has been that you don't want to be prohibited from screwing up. You literally said "not saying don't add safer options, just don't prevent me from shooting myself in the foot".

Where's the contradiction? Add the safer options, but also don't prevent me from shooting myself in the foot.

I'll choose when I wanna use the safer options or not. I've been repeatedly saying C++ has safe options and should continue to add more. What I'm saying is don't remove my ability to code dangerously should I choose to do so.

A "safe" language cannot permit code that could potentially lead to UB, even if it's perfectly safe when coded right. That would ruin C++ in my humble opinion.

If you write a language designed for safety, sure have unsafe blocks. I don't think badly of Rust at all. But C++ is not Rust and, I would argue, has nothing to gain from becoming copy of Rust. Rust already exists!
Last edited on
But C++ is not Rust and, I would argue, has nothing to gain from becoming copy of Rust. Rust already exists!
It doesn't need to become a copy of Rust. Rust for example doesn't have OO. What it does need to do is enforce safety by default. I fear it may fade into irrelevance otherwise. They can make the transition as gradual as they want, but it does need to happen.
Last edited on
I agree with Helios, but I am not sure it can be fixed without wrecking it.
It may not be the worst thing to do-over and let C++ fade. Honestly its D++ or E++ at this point, if you look at just how different the c++ code is now from around 1990 ... it IS a new language. It took me too long to realized the truth of that. But ... I am starting to feel unsure as to how much more twisting the language can take trying to grow it to keep up with new languages that are easier to use, less risky, and starting to feel very much like it won't be able to morph that far. Maybe it will, but like the big changes in previous revisions, it will likely really be another new language at that point.

Few computer languages ever truly die, for that matter. Stuff that I though was obsolete decades ago is still in use. If C++ ended and said this is the final version tomorrow, it would still be in use after all of us are gone.
Last edited on
It depends on what you mean by "die". Did COBOL die in the sense that absolutely no one is writing any more code in it? No. But it is true that no one is learning it except to work on projects that are already using it, and no one is writing code in it, except to maintain already existing projects. Languages, both natural and constructed, die gradually by losing mindshare.
die would be not used at all in commercial software that is still in its lifecycle (has some developer(s) working on it when bugs are found, can still buy it).

dunno what that entails... maybe like A & B (forerunners of C) or other really dead stuff that never even took off.
Last edited on
How about Visual Basic? That thing died pretty hard when MS implemented the gradual transition to C#. I'm not sure you can even install it in the current version of VS.
VB can be installed in VS 2022, in conjunction with C#. There are two separately selectable component options available in the installer or the overall .NET desktop development workload.

https://devblogs.microsoft.com/dotnet/whats-new-for-visual-basic-in-visual-studio-2022/

https://visualstudio.microsoft.com/vs/community/
Human languages have a tendency to change over time, just as a lot of computer languages do, though a lot slower. Human languages also have regional dialect variants.

Languages can change even within most people's lifetime. Compare what was common back in 1980's US to now. Or the 1950's.

Demanding a computer language stay static is not a good thing, especially if the changes improve its reliability and robustness. Too often how C++ is taught even now is what the teachers/professors learned years ago. Is today's Java the same as when it was first released? Rust has undergone adaptation as well.

"Saint" Bjarne Stroustrup overall likes how C++ has changed since he first proposed it, better able to express what he wants to do. (Can't find the quote at the moment)

Sometimes what the standard committee decided to add is rather trivial and/or of narrowly focused usage.

As a self-taught programming hobbyist a somewhat large chunk of what the C++ stdlib provides isn't useful for what I normally do.
Speaking of languages available in VS, has anyone had experience with F#?
I like this quote:

Bjarne Stroustrup wrote:
More good code has been written in languages denounced as "bad'' than in languages proclaimed "wonderful'' - much more.
I agree with Helios, but I am not sure it can be fixed without wrecking it.

Which was one of my points. But I don't see a need for "fixing" it so dramatically. Give defined behavior to things that cannot be avoided (overflows) and give plenty of alternative coding routes for everything else.

This keeps backwards compatibility, makes the language safer, and allows programmers to adapt to the changes to create better code as they see fit.
Last edited on
allows programmers to adapt to the changes to create better code as they see fit.

If programmers would create better code, then there would not be a problem in the first place?
If programmers would create better code, then there would not be a problem in the first place?

There's a difference between having a tricky path to writing good code and having the tools to make it easy to write good code.

You get dangerous code because the language does not offer alternatives to the easy-to-screw-up parts.

You probably know when a pointer is easy to handle versus a pointer that'll be harder to care for in complex code - where a different type of pointer that handles itself would be useful.

When safe features arrive, companies will likely mandate their use as well.
No, you get dangerous code when the language/implementation doesn't stop you from writing dangerous code. See my example on iterating on a container that is being modified. It's not that the language could not possibly stop you from writing code like that, it's that it doesn't.
If there's a path, someone will take it. That's just how people are. The only way to get secure software is to make dangerous code either impossible or highly visible.
See my example on iterating on a container that is being modified

Yes, which can also be useful. You just have to check that the iterator does not go beyond the array bound.

If there's a path, someone will take it

I feel like a 2nd amendment advocate arguing this position. Like I'm arguing that I should have the right to a gun, and you're arguing that if people have guns someone will use it for evil.

Yes people will always screw up. But that doesn't mean I want it such that no one can ever screw up. Give the tools such that if someone does screw up, it's their fault for not using the correct tools, not the language's fault for not supplying such tools.


And I do think C++ has a bad history with supplying the correct tools. There are so many pointer wrappers that are "safer", but they are so convoluted with so many of them that no one ever actually uses them.

C++ can do better, but I don't think it should go as far as suggested here.
Thomas Becker, when explaining rvalue references back in 2013, quipped:
As we all know, the First Amendment to the C++ Standard states: "The committee shall make no rule that prevents C++ programmers from shooting themselves in the foot."

Whether serious or not, it is a leap from that tradition to "make it impossible".

Yet, "highly visible" does have its issues too; programmer can turn off all compiler warnings. Even if that programmer is then clearly at fault, the blame will go wider when bad code does bad things.
Yes, which can also be useful. You just have to check that the iterator does not go beyond the array bound.
??? Modifying a container invalidates iterators, and using those invalidated iterators has UB, period.

Like I'm arguing that I should have the right to a gun, and you're arguing that if people have guns someone will use it for evil.
I'm saying C++ should not be a gun with a hair trigger and a "point at foot" switch that resets to the "yes" position every time you pick it up. If it must have that switch, to activate it one should have to perform a very deliberate action that couldn't happen by mistake, such as inserting a key.

Why do we tie resource management to lexical scope? Because we know that, however careful we are, sooner or later we're going to fuck it up and forget to release something, release it twice, or access it after it's been released. If C++ will under no circumstances let me write
1
2
3
4
{
    A a;
}
f(a);
then why should I be able to write other equally nonsensical things that cannot ever be correct?
??? Modifying a container invalidates iterators, and using those invalidated iterators has UB, period.

Yes, but fairly easy to loop with an iterator and erase:
1
2
3
4
5
for (auto it = vec.begin(); it != vec.end(); )
    {
        if (...) it = vec.erase(it);
        else  ++it; // Only increment if no erasure
    }


Erasing returns an iterator for this very reason I'd figure.

then why should I be able to write other equally nonsensical things that cannot ever be correct?

If something "cannot ever be correct", then I'm on your side to strike it down. But this does not eliminate undefined behavior (and I'd argue not even most of it).

If something like pointer arithmetic is done, it can be right or wrong - hence I don't think it should be restricted.

Something that can never be correct, sure, make it unacceptable.
Pages: 123456