In particular, the capturing semantics with [&] are going to result in a big surprise (use after free) if you try to close over and capture variables like you do with node.js.
I agree, that it can be a big deal and one must think about ownership and lifetimes whereas in Javascript there is no need to. Especially in code that will exit the surrounding function before the callback is executed, I do not use &, and explicitly specify the captured variables so I can think about what type of capture.
However, C++ is improving in this regard. I think lambda capture initializers with C++14 help in this regard so that unique_ptr can be used. In addition, the memory safety tooling is improving - see Herb Sutter's CppCon 2015 keynote. Finally, C++17 should have co-routines which will make this type of callback code less used and allow one to use "normal" logic without callbacks that will also be non-blocking.
> I think lambda capture initializers with C++14 help in this regard so that unique_ptr can be used.
They're still opt-in—the burden is on the programmer to get it right.
> In addition, the memory safety tooling is improving - see Herb Sutter's CppCon 2015 keynote.
Sure. But it's not here yet, it requires a lot of annotations, and there are several key unanswered questions that I didn't see an answer to (how the static analysis deals with pointers derived from shared_ptr when it relies on all pointer function parameters being unaliased, for example).
> Finally, C++17 should have co-routines which will make this type of callback code less used and allow one to use "normal" logic without callbacks that will also be non-blocking.
And when the coroutines suspend/yield, you have the exact same issues regarding dangling pointers and use-after-free.
Got no expertise there. I always assume it with C or anything derived from it. But C++ commenters here keep telling me modern C++ and its libraries have all kinds of ways to prevent common issues with memory. They've demonstrated a few. So, I'd be curious to see a comparison of what happened in practice between the two.
That said, typical C++ applications might be easier to get right than Javascript runtimes, JIT's, or whatever. A lot of eyes go into the JS foundations but so do a lot of complexity and problems.
It is true that modern C++ with the proper tools can mitigate many of the issues that come from C heritage.
The sad reality is that despite the tools that C++ offers for memory safety, the majority of enterprise developers don't buy into them and the code looks more like C with classes than anything else.
If you look at CppCon 2015 when Herb was presenting the Core Guidelines and the new VSC++ static analyzers, only 1% of the audience said they ever used one.
From what I have seen, the issue is that in big risk-adverse entreprise, the mentality of "don't change anything if it works" goes a bit too far.
I feel a bit ashamed, but to give you some rough idea of the age of the toolchain, the c++ compiler we are using does not even support namespace. We are slowly fazing out old platforms but this is really a long drawn struggle. Basically you have to wait that the underlying HW is not produced anymore for 10 years, before maybe thinking the SW side should be upgraded.
I would be very eager to use some nice feature of Cpp11 but it won't be in this company...
No reason to be ashamed, I have seen many companies that only use platform SDKs (e.g. aC++ on HP-UX) and IT has the last word over what tools are allowed on dev machines.
However the situation is no different in other languages.
I am aware of some companies still using Java 5 on production, just to cite one example.
I know one major retailer whose terminals are all a DOS variant whose sales ended in 1999 and whose inventory is hard-tied to SCO UNIX. Got future-proof written all over those. ;)
Note: Many key operations, including the backend, are on AS/400 and mainframe. Much wiser choices. Needless to say, the employees tell me that part never goes down.
> If you look at CppCon 2015 when Herb was presenting the Core Guidelines and the new VSC++ static analyzers, only 1% of the audience said they ever used one.
That's interesting.
It's especially interesting to note that those static analyzers work on unmodified code! The work-in-progress ISO Core C++ lifetime profile does not work on unmodified code and requires a lot of annotations…
> That said, typical C++ applications might be easier to get right than Javascript runtimes, JIT's, or whatever. A lot of eyes go into the JS foundations but so do a lot of complexity and problems.
It is untrue that typical JavaScript applications are vulnerable to anywhere near as many memory safety issues as C++ applications are. Even "modern C++".
As a very relevant example, closures are modern C++, but neglecting the right annotation on the capture clause—the difference between writing one ampersand and not—can lead to use-after-free. In JavaScript, the runtime will manage the lifetimes of the closed-over variables for you, and you can't get it wrong unless there's a bug in the JS engine. Accidental use-after-free due to JS implementation bugs is so rare that I wouldn't be surprised if it's never happened in practice.
>It is untrue that typical JavaScript applications are vulnerable to anywhere near as many memory safety issues as C++ applications are. Even "modern C++".
Note the emphasis on accidental memory safety violations.
There's an enormous difference between attackers running JavaScript that they control and attackers having to exploit memory safety issues in JavaScript that you wrote. Virtually all attacks against JavaScript JITs have been of the former type, in that they rely on perfectly crafted hostile JavaScript that nobody would write on purpose. But in a node.js type of server side scenario, attackers do not have the ability to run arbitrary JavaScript. They only have the ability to interact with the JavaScript that was already written to be non-malicious. So it's much, much harder for an attacker to exploit memory safety problems in the JS engine in a server side scenario—so much harder, in fact, that I wouldn't be surprised if it's never been done.
If your argument is that JS JITs are hard to write, well, sure. But I think that's totally irrelevant to this conversation. Clang and LLVM are also hard to write and are just as trusted in this scenario.
"Note the emphasis on accidental memory safety violations."
Good points. Of course, I'm guessing you're saying it's still really hard to write memory-safe code with modern C++ constructs whereas others here suggest it's pretty easy. That point is tripping me up in these discussions. Did a quick Google on C++ safety and found you already said something about the topic:
My statement is predicated on the premise that modern C++ can be done safely without issues like that. If not, then it's false and we're back to me recommending safer, systems languages.
One thing to remember, though, is that there's tools to automatically transform C code into safe code. Softbound + CETS comes to mind. Might be able to use a C++-to-C compiler with one of those. There's also safer forms of C++ like Ironclad C++.
http://gladdy.github.io/c++/2015/07/26/NodeDemystified-pt1.h...
source code: https://github.com/Gladdy/Mininode