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…
Modern C++ Won't Save Us (2019)
211–220 of 266 posts
Re: Modern C++ Won't Save Us (2019)
#212C++ 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…
Re: Modern C++ Won't Save Us (2019)
#213Earlier 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…
Re: Modern C++ Won't Save Us (2019)
#214My 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…
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)
#215I 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…
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)
#216Earlier 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…
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)
#217Earlier 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.
Re: Modern C++ Won't Save Us (2019)
#218Earlier 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)
if(!bla)
return;
// use bla
early-return style. So that's really a no-go for me from years comparing the two stylesRe: Modern C++ Won't Save Us (2019)
#219Is 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
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)
#220Earlier 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
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.