This blog post writes a dissertation about garbage collection, heap memory management, the absolute need to take courses on assembly language, and other contrived and absurd tangents.
Looking at the code, the guy gets a double-free because he instantiates two
std::unique_ptr
from the same raw pointer.I’m sure the author felt very clever to pull up all these topics to write a blog post about, but in the end all they’re doing is writing buggy code based on their misconception of a topic.
You can call it writing buggy code based on misconceptions, but the fact that it’s possible (and not even especially difficult) to misuse smart pointers badly enough to produce program crashes and undefined behavior is still a fundamental weakness of C++ as a language.
As a counterexample, this type of bug is impossible to produce in Rust without explicitly using the
unsafe
keyword, and that keyword is something that is almost never used by regular developers and is an easy thing to audit for.Edit: That being said, if you’re stuck using C++ then obviously using smart pointers is the right thing to do whereas using raw pointers and managing the memory yourself is completely asinine, so if the author’s point is to not use smart pointers in C++ then I suppose they want you to just… Leak memory? Because if you’re able to figure out where it’s safe to free a raw pointer, then you’re able to figure out how to correctly use a smart pointer in that situation.
It’s maybe a weakness if you dont know what you’re doing, the strength and power of C (and thus if you wish C++) lies in just that you can manipulate memory directly with just a raw pointer however dangerous it is.
This statement is incredibly naive. I know exactly what I’m doing with C++ and yet it’s still incredibly easy to introduce subtle bugs as soon as you’re developing anything moderately complex, especially when async or threading are involved. It’s not that I’m unaware of what problems may happen, it’s that the language expresses itself poorly and a subtle typo or innocent assumption can lead to catastrophic failures that might only surface in 0.0001% of the times that a certain line of code is run.
I used to consider C++ my favorite language by an enormous margin because I assumed that we just have to accept the danger to get the benefit of performance. I used to eagerly follow developments coming from the C++ ISO committee, excited for the language improvements that would be coming down the line.
Then I started playing with Rust and learned what it’s like to get incredible performance without being mired in hazards. Imagine outperforming C++ on average while also having your code almost always work perfectly the first time you compile it and never crash or segfault. That’s Rust, and once you give it a fair try, you’ll never want to go back to C++.
Being able to manipulate raw pointers with no guardrails ever is not a strength, it’s a terrible weakness, and you’ll live a happier life the sooner you realize that. Consider instead if you could have all the same level of control over memory except the compiler tells you whenever you’re doing something asinine before you run it. You can always force it to do what you’re asking for by declaring it
unsafe
but you’ll quickly realize that you never actually want that.Well then you’re better off with Rust! I have heard the same thing about Java, C# and even scripting languages like Python. It suits you and the project? Go for it!
But the raw pointer in C (and thus C++) is the absolute power, and that’s about it. That is how computers are built, that is how compilers work, that’s how about anything works under the hood. Like it or not.
You dont have to like it, I understand that completely.
Absolute power doesn’t have to come with unnecessary risk everywhere. There’s nothing you can do in C++ that can’t also be done in Rust, the difference is that Rust keeps it safe by default and you need to go out of your way to say “Let me do this incredibly risky thing inside this specific block of code” before it lets you do anything that has any risk of leading to undefined behavior and crashes.
And it turns out, you can have all the performance advantages of C++ while almost never needing to do anything unsafe. The average Rust developer will never use the
unsafe
keyword in their entire career but will still write code that outperforms the average C++ developer.Yeah, I have been a long for some time and that was the speech for Java, C# etc too you know.
Real like isn’t usually coding a new program with unsafe pointers for speed, it’s usually a 20 y old codebase in C/C++ that interferes with third parties in C, C++, C# and two distinct versions of Java, incompatible between each other.
So maybe Rust is the new deal, like Python was supposed to be and Java before that, we’ll see…
Python never claimed to be the new deal, neither did java. At least not in the “c++ is now obsolete” way.
Rust definitely can replace c++, the major reason for not doing so right now is the legacy stuff, but as rust / c++ interop improves I think we will see more companies moving away from c++.