Live data from Hacker News

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

alexgaynor.net

211–220 of 266 posts

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

#211

Earlier quoted context omitted.

> 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 big…

> You allocate a memory arena when the HTTP request comes. The per-request-arena concept is one of the most powerful and IMO underappreciated tools out there for dealing with memory-lifetime issues. I've used it or advocated for its use at multiple jobs and projects, quite successfully, even for kernel code. Windows NT uses it in IRPs. Network code in both BSD and SysV did something pretty similar, at least in the lo…

A nice, obvious way to get a per session arena for almost all resources is to fork a process.

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

#212
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…

OOP and Boost also Templates has benefits when it comes to increasing barrier of static reverse engineering. For example, Security researcher "Marcus Hutchins" famously echoed that Boost is a cluster fuck of OOP sadness [0] Similarly, a close friend of mine "Omer Yair" mentioned [1], "A well written OOP malware might be harder to RE statically than a poorly written C code. Writing OOP malware badly though just makes…

there is very little OOP in boost.

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

#213

Earlier quoted context omitted.

The solution for C would be to "stamp out" a specialization of qsort() for a specific data structure either manually or with code generation. The C++ template system really isn't some "magic performance pixie dust", it just saves some typing ;) ...or alternatively, with global optimization (LTO/LTCG) there's actually a good chance that the comparision function calls of a C qsort() implementation can be "dissolved" vi…

Much of what you say is true, but I'm not sure that this is: > (on the other hand, C++'s "zero cost abstraction" philosophy requires the same level of trust). The C++ Standard _requires_ that a Standard Library implementation implements certain performance guarantees - I don't think the C Standard has such requirements. This means that certain implementations are effectively required - for instance that std::map is i…

To be clear, the standard mandates the complexity of most standard library functions. In no way it mandates zero copy abstraction (and it is not clear how one would even word that). Features are usually defined in such a way that zero cost abstractions are at least known to be possible though.

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

#214
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 think the biggest problem with C++ is the lack of explicit safety requiring you understand the internal mechanisms of how everything works in order to make use of almost anything, combined with extremely high levels of abstraction.

The high levels of abstraction are powerful, but quickly become footguns to the uninitiated (and the initiated alike at times).

> Figuring out how to do something safely can be quite difficult. It can involve solving puzzles, and often involves rewriting things at several levels, especially when threads are involved.

I think this gets to the core of really closing the gap. While the "insider" knowledge of C++ is really understanding the internal workings of these abstractions so you don't do something stupid with memory, the "insider" knowledge of Rust is knowing the specific patterns and routes that will work with the safety features of the language rather than against it for solving various problems.

I can still say for me I spend a lot of time 'exploring' Rust, having the compiler bitch at me, and tweaking things about until they work.

Sometimes it can be extremely frustrating, and given I have the insider knowledge of C++ with 20+ years experience, it's easier for me to just drop in and do exactly what I want to do (because I know it's safe... or at least I think it is ;) )

That being said, I'm very excited for languages like Rust, but there is still a gap of cost/benefit between it and C++ for the time being, at least for my professional use.

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

#215

I love C++ and I’ve to admit that it will need a subset language soon but the examples given in this article wouldn’t possibly exist in well checked code-bases because you can immediately see usage stinks just by looking at it. I think every C++ is bad article can be summarised like this: 1. C++ has lots of features. 2. Let’s nonsensically combine these features to shoot ourselves on the foot. 3. Uh oh, C++ didn’t he…

To add, C++ has survived for many years as the defacto system-level programming language (C has too). It has survived good and bad shifts in software engineering.

The old "C++ is not going anywhere" argument applies.

C++ is not great choice for small, or transient projects. There are other languages that are a better investment for those projects.

But if you're writing an infrastructure-level application, that is expected to have a shelf life in decades, C++ (or C) is a pragmatic and rational choice.

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

#216
post #90

Earlier quoted context omitted.

> Optionals are not zero-overhead in any other language. This is a common misconception, and a pet peeve of mine. Properly designed optional types add neither space nor code-size overhead. Consider the C function: foo(int* ptr) { ... } If it is part of the API of foo that `ptr` may be null, then foo must not dereference `ptr` without verifying that it is non-null. So the body of foo must be something like: foo(int* p…

> If it is part of the API of foo that `ptr` may be null, then foo must not dereference `ptr` without verifying that it is non-null. So the body of foo must be something like: foo(int* ptr) { if (ptr != NULL) { ... } } then what ? foo(int* ptr) { if (ptr != NULL) { *ptr += 1; // optional ::operator* would introduce a branch here ? *ptr = *ptr / 2 ; // same if(*ptr > some_constant) // same { ... } // etc etc } } and c…

That’s why I said properly implemented! Good optional implementations let you do the check once to unwrap the inner value, so you have one branch.

In rust:

    fn foo(s: Option) -> {
      if (let Some(inner) = s) {
        // now you can access inner repeatedly
        // without branches
      }
    }
(edit to fix syntax errors)

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

#217

Earlier quoted context omitted.

> You allocate a memory arena when the HTTP request comes. The per-request-arena concept is one of the most powerful and IMO underappreciated tools out there for dealing with memory-lifetime issues. I've used it or advocated for its use at multiple jobs and projects, quite successfully, even for kernel code. Windows NT uses it in IRPs. Network code in both BSD and SysV did something pretty similar, at least in the lo…

A nice, obvious way to get a per session arena for almost all resources is to fork a process.

Um, yeah, but there are other issues that make it not so nice. And it's an inoperative concept for most kernel/embedded work. I'd say in most contexts where forking would be OK you should be using a GC language anyway.

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

#218
post #216

Earlier quoted context omitted.

> If it is part of the API of foo that `ptr` may be null, then foo must not dereference `ptr` without verifying that it is non-null. So the body of foo must be something like: foo(int* ptr) { if (ptr != NULL) { ... } } then what ? foo(int* ptr) { if (ptr != NULL) { *ptr += 1; // optional ::operator* would introduce a branch here ? *ptr = *ptr / 2 ; // same if(*ptr > some_constant) // same { ... } // etc etc } } and c…

That’s why I said properly implemented! Good optional implementations let you do the check once to unwrap the inner value, so you have one branch. In rust: fn foo(s: Option ) -> { if (let Some(inner) = s) { // now you can access inner repeatedly // without branches } } (edit to fix syntax errors)

but this declares a new variable - I find this super messy and really decreases readability in practice since now it's not obvious anymore that what you're working with was a function parameter. Also it adds a scope level - I much prefer the

   if(!bla)
     return;

   // use bla
early-return style. So that's really a no-go for me from years comparing the two styles

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

#219
post #119

Is there a safe subset of C++ defined somewhere? Can I turn off some of these ridiculous "features"? As we add so much to the language, the number of footguns increases quadratically.

Yes, C++ the good parts is known as C++ Core Guidlines, https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines

This is great stuff. Thanks!

I sympathize that compilers do not do "enough" of this for us. But there's really no substitute for a good code standard and developer culture focused on quality.

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

#220
post #216

Earlier quoted context omitted.

That’s why I said properly implemented! Good optional implementations let you do the check once to unwrap the inner value, so you have one branch. In rust: fn foo(s: Option ) -> { if (let Some(inner) = s) { // now you can access inner repeatedly // without branches } } (edit to fix syntax errors)

but this declares a new variable - I find this super messy and really decreases readability in practice since now it's not obvious anymore that what you're working with was a function parameter. Also it adds a scope level - I much prefer the if(!bla) return; // use bla early-return style. So that's really a no-go for me from years comparing the two styles

Well if you have aesthetic objections to the way rust does it, I can't argue with you. Kotlin does it the way you like, though.

Anyway, I started in on this thread because I was objecting to the claim that optional types always have overhead. They don't. That's all I wanted to show.

Post reply on HN