Hacker News new | ask | show | jobs
by croes 962 days ago
The people who are in for the fun won't use the typescript model for long either.

If it's optional it will be omitted in the hard parts, for instance if your favorite library doesn't support it.

2 comments

It's still worthwhile even if you have to fudge module boundaries or skip the hard parts. Kind of like having "safe" Rust wrapping "unsafe" C boundaries doesn't make the rest of Rust not worth it. Lying about the type internals of your function is still preferable to the wild-wild west of JS.
That's why incremental adoptability is so powerful. Slightly ironically that's exactly what (AFAIK) made C++ so popular: You can start using it without really giving up anything. And ideally once you see the benefits you'll be hooked and want to (incrementally) use it more and more throughout your code.
And exactly what makes C++ codebases so hard to clean up from C idioms, as many developers to this day apparently never went beyond changing the file extension, regardless of how many security advocacy we keep telling them.
C++ adds so many additional security footguns over C, that I find this line of reasoning hard to accept. The problem with C++ is not that people are using C constructs with it, the problem is that the language design itself is deficient.

Are you aware of any systematic review that shows evidence that C++ is safer than C?

The rate of safety defects between major C and C++ projects appears similar at first glance, and both way worse than managed languages or rust.

I have written a lot of the same kinds of data infrastructure software in both C and C++ and other languages, so comparison is somewhat reasonable (unlike comparing e.g. web browsers and systems software). The rate of defects is much lower in modern C++ versus C, and the types of bugs have changed too, but only part of that can be attributed to safer constructs in C++.

C requires many times more lines of code than C++ to do the same thing. AFAIK there is considerable academic evidence that bug counts roughly scale with lines of code, so languages that are precise and concise naturally reduce total defect rates. Minimizing defects requires maximizing expressiveness. The ratio of LoC between languages to express the same thing is not constant, it depends on the application.

The kinds of bugs I see in C++20, given the type of software I work on, are almost entirely the same kinds of logic and behavioral bugs that occur in every language. This is why Rust isn't as popular as one might expect for systems software: memory safety bugs are not a thing for many code bases, and Rust requires many more lines of code compared to C++20. I am sure Rust will become more economical over time but for now it is pretty verbose and has pretty limited metaprogramming functionality.

C++20 is remarkably safe and concise if you take full advantage of the type system.

> C++20 is remarkably safe and concise if you take full advantage of the type system.

Against what sort of laughably low bar are you measuring to make C++ "remarkably" safe ?

This is a language which delights in deliberately adding more footguns, on the rationale that well, it's less safe so surely it'll be faster right? No need to measure, no need to investigate what actual performance optimisations might somehow be available if we allowed the dangerous behaviour, no, just mandate it and YOLO.

C++ 20 introduces std::span. Now, std::span is basically a slice type, Rust's [T], and to some extent it's remarkable that C++ didn't have a slice type, but that's C++ for you. What's fascinating is that in 2020 I remind you they standardized a type which deliberately has no safe way to use it. It was proposed as a safe type, and WG21 stripped out the safety on the rationale that now it's faster (see above) then rejected all attempts to add the usual half-arsed C++ safety features to the type now that it wasn't safe by default.

Let me quote a C++ proposal paper (this isn't some hit piece from Rust fanatics, it's a serious proposal to the ISO working group) P2821 on std::span:

"Ultimately, this becomes a stereotypical example of how C++ traditionally handles safety. this example gets to be pointed at for years/decades to come. All of this could have been avoided"

You can replace almost everything in C++ with stricter implementations of your own design if you don't like the behaviors or guarantees of the standard/default implementation. Many people do because the language is very amenable to it and the codegen is usually optimal. Living entirely within the standard library and the constraints it imposes to support backward compatibility is a choice, not a requirement. The standard design is always going to be less than ideal for some subset of applications, it is an unavoidable tradeoff.

The metaprogramming facilities of C++ are strong enough now that there is little that can't be customized without macros in a way that is nearly transparent.

Yes, it starts by not coding in C++ as if it was C.

Use templates instead of macros, RAAI instead of gotos, namespaces instead of prefixes, bounded checked strings and arrays instead of raw pointers, new instead of error prone sizeof with malloc(),...

> The rate of safety defects between major C and C++ projects appears similar at first glance

How come? Surely there would be fewer memory leaks in a code base with proper RAII than in C code with malloc and free all over the place.

Yes, this is a common theory, but I don’t see evidence for it in the hard numbers. Taking two of the most popular projects in each language, with a comparable LOC count, the numbers look surprisingly similar year over year:

Linux kernel (C): https://www.cvedetails.com/product/47/Linux-Linux-Kernel.htm...

Chrome (C++): https://www.cvedetails.com/product/15031/Google-Chrome.html?...

There’s some variability year over year, but if anything C appears to have a slight advantage over C++ in terms of memory corruption (840 vs 1004), with essentially the same number of overflow errors (322 vs 328). There is no comparable rust project, but initial evidence from the asahi gpu drivers hints that memory corruption errors are fundamentally eliminated.

This is obviously not accounting for confounding factors, hence my request for any peer reviewed evidence for the security claim. Until then, the facts don’t seem to be supporting it.

Are you seriously putting the Linux kernel forward as a typical C code base? Isn't that a bit like selecting the example of an F1 car to show that cars are usually at least as fast as motor cycles?
Chrome is a vastly more complicated program than Linux.
You're assuming that all, or even most, C++ codebases use proper RAII and don't run wild with the vast amount of features in the language and standard library.
C++ containers such as std::vector and std::array have bounds checking at least, though I have not saw them used very much.

Bounds checking instantly eliminates buffer overflow related unsafety, but not having it as the default is not good.

The trouble with bounds checking via generics/macros is that the compiler doesn't know how to optimize out the checks. Most bounds checks can be optimized out of inner loops, where it really matters. But if the overflow test is just ordinary code, the compiler can't do that.

You also want to hoist bounds checks and do them early. Often, one check at loop entry can eliminate the bounds checks for each iteration. But the language has to allow an early fail.

They have bound checking through the `vec.at(index)` method, not through the indexing operator `vec[index]`. Most people won't even look at the `at` method, they will just use the indexing operator since that's supposed to be the "default" .
While true, most compilers do enable bounds checking in debug releases, and there are compiler flags to keep those checks enabled in release builds.
But you can't deny that C++ is a straight upgrade to C. If CppFront becomes this straight upgrade to C++, isn't that a good thing?
C++ extended C syntax, did not introduce a completly different one alongside.
Does that make it not an improvement? There's definitely issues with C++'s syntax...