> Rust also has UB, btw
Not at all the same. C and C++ are full of hazards and I get the impression it’s genuinely difficult to avoid entirely in normal code bases, and typically impossible to avoid statically. Whereas in Rust it’s all gated behind the unsafe keyword, and if you don’t use it (and most code bases never need to use it), you cannot encounter UB; and that scoping makes it far easier to control and handle correctly.
I think this is a bit exaggerated. I mostly find it not difficult to avoid UB in C. There are mainly five areas where you can have problems: type safety issues, signed integer overflow, out-of-bounds accesses, use-after-free, and race conditions. Type safety is generally not a problem if you avoid unsafe casts (and casts are easy to screen for just like "unsafe"), signed overflow one can protect against via sanitizers or one can rule it out statically, and out-of-bounds accesses you can avoid by using safe buffer and string abstractions and never doing open-coded pointer arithmetic.
Use-after-free and race conditions are the areas where Rust has a clear advantage. Here one needs to have a clear strategy and enforce it manually (or using tools, but we lack good open-source tools for this). Valgrind and similar tools also help.
Almost but not quite. You are promised that safe Rust doesn't have Undefined Behaviour, but that's cultural, not technological. The technology is just enabling Rust's culture to deliver what they promised, but it would be very easy to purposefully (indeed there are known bugs where it does happen, look for "Rust soundness bug" if you want examples) inject UB which happens in your safe Rust.
The extent to which this is about culture should not be underestimated, to me that's the most hilarious part of Bjarne Stroustrup's big rant on memory safety a few years ago. The C word appears exactly once in his slides, in a quote from somebody else about what needs fixing. But Bjarne never addresses this once, even though it's the actual problem.
Sure Rust is better on it, my point is that it is there, despite that community making it a Big Freakin' Deal to have all the memory safe they could design into the compiler and language.
If even they had to add escape hatches despite the presences of powerful language primitives like types, traits, borrow-checking, maybe the people charged with making it all work with 80s compiler technology weren't the literal Antichrist for also having UB as Rust does.
For what it's worth, C and C++ are much different in terms of hazard, so when you bucket them together it makes me wonder how familiar you are with the actual risk of UB in practice.
Nowadays it generally stems from doing weird things.... but no one is making you do weird things, any more than people are making you use Rust's unsafe keyword.