Live data from Hacker News

Modern C++ Won't Save Us (2019)

alexgaynor.net

31–40 of 266 posts

Re: Modern C++ Won't Save Us (2019)

#31

> There are significant challenges to migrating existing, large, C and C++ codebases to a different language – no one can deny this. Nonetheless, the question simply must be how we can accomplish it, rather than if we should try. Um... no. Not every (or even most ) existing large C/C++ codebase should be migrated to another language. "But security vulnerabilities! And crashes!" I admit all that. But a program can be…

This amounts to saying that we should accept codebases continuing to contain exploitable vulnerabilities indefinitely. Perhaps for codebases that have a finite expiry date that's tolerable, but for a codebase that's expected to be maintained indefinitely I don't see how it can possibly be worthwhile - a rewrite will be a one-time cost, whereas exploitation is an ongoing cost that will surely exceed the one-time cost eventually.

Re: Modern C++ Won't Save Us (2019)

#32

Earlier quoted context omitted.

> Ideally that should be zero-overhead Optionals are not zero-overhead in any other language. If you aren't going to bother checking the optional, why not just return any old pointer type? The type system should be used to enforce a contract and bypassing checks on that feels like you are just spitting in the fact of the type checker.

> Optionals are not zero-overhead in any other language. That's been true for so many other features in C++ too. > If you aren't going to bother checking the optional, why not just return any old pointer type? Pointers require something to point to. Optionals can embed the value. > The type system should be used to enforce a contract and bypassing checks on that feels like you are just spitting in the fact of the typ…

> And I mean, you could use this logic for everything else. Iterators, arrays, etc. should all have bounds checking too, right? If you want that, there's C#...

I mean yes, the logical conclusion is that trying to backport safety onto C++ is impossible and moving to another language is the only reasonable option. That's kind of the point of the article.

Re: Modern C++ Won't Save Us (2019)

#33
post #2

UB-invoking dereference in std::optional is such a baffling design choice. The whole point of an optional type is to prevent accidental unchecked access to the value. Sure, sometimes it's useful for performance to skip the check when it's already known-safe from the context, but such dangerous optimization should have been behind a method like `beware_of_the_nasal_demons()`, not an innocent-looking convenience syntax…

boost::optional was designed to mimic pointers. Before boost::optional, some programmers would return a T* as a caveman's optional . Boost wanted to preserve the syntax of *, ->, and operator bool. Dereferencing a null ptr is UB, so operator* for optional was the same. I agree it would be nice if you could get an assert in operator*. But you can already fire up a debugger or sanitize build and get a nice error messag…

> it would be nice if you could get an assert in operator*

If, as you wrote, operator* for an optional that doesn’t contain a value is UB, it can do whatever it wants, including assert.

I think the problem is that there’s an implicit requirement that operator* optionals that do contain a value is as fast as a pointer dereference.

(Aside: reading https://en.cppreference.com/w/cpp/utility/optional, I wonder how one can misuse “When an object of type optional is contextually converted to bool, the conversion returns true if the object contains a value and false if it does not contain a value.” to write obfuscated code or hide back doors using optional)

Re: Modern C++ Won't Save Us (2019)

#34
post #24

My comment for too many years is that C/C++ fails to deal with three issues: "How big is it", "Who owns it", and "Who locks it". C++ has, with difficulty, made progress on "How big is it" through templates, but raw pointers keep leaking out. "Who owns it" has been tough to deal with, although "owned pointers" at least try. "Who locks it" has yet to be addressed at the language level, although at least there's now som…

> three issues: "How big is it", "Who owns it", and "Who locks it"

The issue with this kind of thinking is the belief that there is a "it", not "they".

Say, you are writing a HTTP server [1]. A beginner mindset (what seems to be demonstrated in this post) with start allocating left and right, for every HTTP header, for every piece of string, for every piece of metadata record, etc. Thus, "how big is it" become no bigger than it needs to be. The lifetime of these allocations and deallocations will be made as "narrow" as possible, meaning that the programmer will try to deallocate as soon the they stop needing the data stored; "who owns it" becomes the user of the data itself. And so on.

However, think of an alternative strategy, something which game and embedded developers have been using for decades. You allocate a memory arena when the HTTP request comes. From that point on, every "allocation" is equivalent to bumping a pointer in that arena. If the arena gets full, we allocate another and chain it to the previous one, as a linked list. No deallocations are performed (or could possible be performed) until the Request is parsed, relevant processing is done, and Response is constructed and sent. At this point, the entire arena chain associated with that particular request-response cycle is deallocated in one go.

How big is it? We don't care, smaller than the arena.

Who owns it? That particular request-response cycle.

Who locks it? No one, if different request-response are parallelised wrt each other; otherwise, depends on the nature of concurrency/parallelism.

[1] Usually, I would have given a gamedev example, and then people would have said that it only works in gamedev. That's why I have tried to give a webdev example, considering the majority demographic on this website.

Some reference:

1. Mike Acton's CPPCon Talk: https://m.youtube.com/watch?v=rX0ItVEVjHc

2. Rant by Casey Muratori (Brusqueness Allergy Warning): https://www.youtube.com/watch?v=f4ioc8-lDc0&t=4407s

Re: Modern C++ Won't Save Us (2019)

#35
post #14

C++ is a beautiful, pragmatic and very efficient language, just constrain your use of it to STL, and avoid Boost and other over-engineered dependencies. The Ockham's razor principle of code design is not only important but essential when using large mature languages that have many surprising and nuanced ways to skin a cat. Being too clever with C++ is a recipe for disaster. Avoid OOP (inheritance in particular) and t…

I'm not sure I understand your points about Boost - everything the article discusses is in the STL, is it not?

I'm also not sure I understand your point about being too clever and template metaprogramming - nothing the article discusses involves template metaprogramming, and I'd say it's doing very straightforward things. Do you think some part of this is too clever?

Also, I'm not sure I understand how to reconcile your "Avoid OOP" advice with the advice to use the STL. Doesn't using the STL mean making use of OOP?

Re: Modern C++ Won't Save Us (2019)

#37
post #36

Yet C++ is what Google, Facebook, Microsoft and others still use for their most mission critical software.

Mission critical software projects, by their nature are started rarely and make very conservative language choices. By its nature, much of it is old, so it's in C++. There's also a fair amount of it in C# and Java, too.

Re: Modern C++ Won't Save Us (2019)

#38
post #10

Earlier quoted context omitted.

I read that sentence as applying to security-critical software. i.e., I don't think the author would insist that Quake II be rewritten in Rust.

Quake III already has been ;) https://immunant.com/blog/2020/01/quake3/

Quake III appears to be C code. The argument for (automatically) rewriting C or nearly-C to Rust is stronger than for C++.

Curiously, they seem to have found just one, inconsequential, memory usage error in the entire, large C program. This calls into question the frequently repeated assertion that there is no substantial and correct C code.

Re: Modern C++ Won't Save Us (2019)

#39
post #32

Earlier quoted context omitted.

> Optionals are not zero-overhead in any other language. That's been true for so many other features in C++ too. > If you aren't going to bother checking the optional, why not just return any old pointer type? Pointers require something to point to. Optionals can embed the value. > The type system should be used to enforce a contract and bypassing checks on that feels like you are just spitting in the fact of the typ…

> And I mean, you could use this logic for everything else. Iterators, arrays, etc. should all have bounds checking too, right? If you want that, there's C#... I mean yes, the logical conclusion is that trying to backport safety onto C++ is impossible and moving to another language is the only reasonable option. That's kind of the point of the article.

> I mean yes, the logical conclusion is that trying to backport safety onto C++ is impossible

The logical conclusion is that what some people here seem to want is so radically different from C++ that they really just want an inherently just a different language altogether... which is fine. Nothing about this implies it's impossible to shoehorn C++ into something else (though that may still be true; I'm not sure). It just implies that another language should be considered when you want to prioritize memory safety, like maybe C# or Rust. (And nowhere here am I agreeing or disagreeing with the article.)

Re: Modern C++ Won't Save Us (2019)

#40
post #27
post #24

My comment for too many years is that C/C++ fails to deal with three issues: "How big is it", "Who owns it", and "Who locks it". C++ has, with difficulty, made progress on "How big is it" through templates, but raw pointers keep leaking out. "Who owns it" has been tough to deal with, although "owned pointers" at least try. "Who locks it" has yet to be addressed at the language level, although at least there's now som…

I'm not sure what you mean by "global analysis," but Rust's borrow checker doesn't do any analysis that I'd consider "global."

"Global analysis" is specific compiler optimization terminology. It refers to analysis across so-called "basic blocks" (also compiler terminology). See here: https://web.stanford.edu/class/archive/cs/cs143/cs143.1128/l...
Post reply on HN