12 ms·
> But as more and more engineers joined us, some shortcomings > of C++ came to bite us: unreadable coding style, memory leak, > segmentation fault, and more. *
by mzimbres 4y ago
> But as more and more engineers joined us, some shortcomings
> of C++ came to bite us: unreadable coding style, memory leak,
> segmentation fault, and more.
* unreadable coding style: This is not a C++ problem.
* memory leak: Memory leak is an old C++ problem, since C++11 there is no reason for not using smart pointers.
The only point that could be attributed to C++ is the segfaults perhaps, due to its lack of safety. But your other two points made me skeptical about Rust bringing you much benefit. I am specially concerned about throwing away months worth of code. Rewriting everything from scratch is what newbies love to do and will most likely get you in the same mess you were in. Try to learn with the error of others [1]. And btw, the problem is usually who writes the code and not which language is used.
[1] https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/ https://www.joelonsoftware.com/2000/04/06/things-you-should-...
- flohofwoe 4y ago> since C++11 there is no reason for not using smart pointers. Smart pointers lure you into a dark alley where each tiny object lives in its own tiny heap allocation, and before you know it you have so much memory management sprinkled decentralized all over your code base that the memory management overhead becomes a performance problem, but at the same time it's too late to do anything about it because it would mean rewriting everything (this is then usually when the desperate search for a silver bullet like a "high performance memory allocator" starts). (not that Rust is necessarily better in that regard when people start to work around borrow checker restrictions with Box and Rc...)
- gpderetta 4y agoI don't understand. Smart pointers replace dumb pointers not normal stack/inline object placement.
- flohofwoe 4y agoYes, but people need to be aware that "auto obj = make_unique..." or "auto obj = make_shared..." should be a very rare thing and not the norm (and I've seen plenty code bases like that). There needs to be a proper memory management strategy with the goal of minimizing heap allocation in random places in the code. E.g. automatic memory management doesn't resolve you from thinking just as much about memory management than doing it manually in the first place.
- gpderetta 4y agoI would hope they are, otherwise why are you even writing C++. I might have too high expectations though...
- flohofwoe 4y agoThe idea that ref-counting is automatically "better" than a garbage collector is still pretty popular unfortunately (and that's just the tip of the iceberg).
- nu11ptr 4y agoA bump allocator + state of the art compacting GC is MUCH faster on a naïve basis which is why it is important to minimize number of allocations in non-GC langs and use stack based RAII when possible. When building things like trees in a non-GC language, arena allocation should be considered for max performance. This is just another low level vs high level trade off IMO.
- pkolaczk 4y ago> A bump allocator + state of the art compacting GC is MUCH faster I can see it repeated very often, but can you point me to any evidence for such claim, based on modern low-pause GCs and real data (not simulation)? I find low pause GCs have pretty substantial overhead and have way lower allocation throughput than old stop-the-world GCs. And the difference between manual memory allocation wasn't that big either (still within 2x).
- jstimpfle 4y agoIt's not about what you use to point to the thing. It's about how you allocate the thing in the first place. Smart pointers are like a free pass to do things without consideration: they allow you to make progress without caring how your things are allocated, because they ease the pain that results from just allocating stuff on the global heap, lacking a systematic approach. Note that while smart pointers ease pain in the short term, there are subtle complications that arise from the constraints that they introduce. One is performance, in some cases the cost of generalized memory management can be too much. Memory fragmentation can be an issue too. RAII the mechanism is not free but requires compatible code and containers. I'm sure there are lots of projects that have broken under the added constraints introduce by such smart classes. And while smart pointers are orthogonal to systematic memory management, if you get the management right the use of smart pointers can easily become a net negative.
- gpderetta 4y agoI don't subscribe to the 'it is expensive so it should be painful' line of thought. That's how you end up with cstrings, strcpy, strdup and friends.
- jstimpfle 4y agoNo, strdup uses a general purpose allocator to put a string in a random place on the heap. Quite the opposite of a well-structured approach. "It is complicated so let's see if there is a simpler approach".
- deleted 4y ago[deleted]
- nu11ptr 4y agoI'm sure it is the same for C++, but in my Rust code things that are put in a Box/Arc etc. are carefully considered and typically my top level business objects. I even wrote my own inline String struct a while back (flexstr) to ensure I don't do allocations for strings smaller than 22 bytes. I don't use allocations "all over the place" without thought and like any language feature, design and placement is important.
- flohofwoe 4y agoThat's much more thought put into memory management than what I was used to in the C++ world from 5..15 years ago where many people seemed to have the impression that allocating and freeing memory or the overhead for refcounting is free. If this is starting to change then it's a good thing.
- CoolGuySteve 4y agoDecent test coverage and ASAN should be all you need to never have a memory leak in C++. ASAN will even tell you what backtrace allocated the thing in the first place.
- cesaref 4y agoI'm not so sure. I've a feeling it's easier to write decent Rust than decent C++. The post contains comments about how difficult they found it to keep coding style consistent and language feature use consistent. This suggests to me an inexperienced team without the skills to manage a project of the size and complexity they need. Now whether with the right team they could produce a better solution in C++ or Rust, i've no idea, but if this is the team they have, then it sounds like Rust might be the right choice for them.
- kubb 4y agoIn Rust you can allocate small structs on the stack while being confident that the plain pointer passed down the stack will be valid throughout the function execution. In C++, you need to use a plain pointer or a unique pointer. The former makes the function leak when passed a pointer to heap. The latter requires a heap allocation and free for the struct contents.
- menaerus 4y agoYou probably want to revisit your understanding because what you said doesn't make much sense. Allocating variables on stack and passing them over to other functions is perfectly fine. If you want them to live on a heap that's perfectly fine too.
- qwertox 4y agoI used to code primarily in C++ around 12 years ago, then moved over to Python. I've now started with Rust and I really love it. I find myself constantly fighting with the compiler, it telling me what it won't allow me to do. In C++, threading was my only way to execute parallel tasks, Python 3 showed me a about coroutines, which I've really started to love. So in Rust I'm experimenting a lot with Tokio right now, and I'm trying to duplicate what I've made in Python. I often think about how good this compiler is that it won't let me do things which I clearly would have done in C++ either to cut corners or, more importantly, out of lack of understanding the consequences. I was creating this WebSocket server which would serve as a bridge to a MQTT broker, all in async code, all in one big file. I was constantly fighting with the compiler about reusing variables or handing them over to tasks. When I then attempted to refactor the code by splitting it into several files, the core of the server in main.rs, some WebSocket-related stuff in websocket.rs, all WebSocket-stuff related to the communication with the clients into websocket_handler.rs and all MQTT stuff in mqtt.rs, all my fighting against the compiler fell together. In my inner eye I could see how the variables were handed over to which file during execution, and that this was the reason why I was no longer allowed to use them in the previous file. So much logic, so clear, and the compiler forced me to do it that way. Then there's the ease of integrating external libraries, which, at least in Windows back then used to be non-trivial in C++.
- ArtWomb 4y agoCloudflare Workers (serverless) + WebSockets is the lingua franca of the internet now. Using languages with built-in concurrent stream processing features is I feel key to moving at internet speeds ;)
- simiones 4y agoThose are both mostly niche technologies, they're really nowhere near "the lingua franca of the Internet". In fact, "serverless" may well be past its peak, with many having tried it in AWS or Azure a few years ago, and then moving on to Kubernetes to avoid the extreme vendor lock-in. And while there are "serverless" frameworks for K8S, they are not as popular as more traditional deployments.
- zaphar 4y agoThe point of safer languages is that it can protect you from the person writing the code. Sometimes that person is someone else. Sometimes that person is you. But no matter who the person is they will eventually have a bad day and some of those bad days will not be caught by a C++ compiler and linter. So your last point is I think probably not correct. The truth is that you need both a competent coder and also a language that catches when you are a little off your game. Rust is one of the compilers that help to catch when you are off that game. Your point that a rewrite is very risky is well made regardless though.
- DrBazza 4y agoI’ve worked on quite a few codebases over the years. Only two were of outstanding quality and robustness. One was Java. The other was C++. What both of those had in common was a single strong tech lead that would veto code with no argument if it didn’t meet standards. I’ve yet to work on Rust but I’ve seen horrific and buggy code in C++, C, Java, Kotlin, C# and of course JavaScript and Python.
- usrnm 4y ago> Memory leak is an old C++ problem, since C++11 there is no reason for not using smart pointers. C++11 did not invent smart pointers, pretty much every C++ project had already been using them long before they were added to the standard. They help with leaks to some extent, but are not a panacea, I can do a memory leak with shared_ptr in just a few lines of code. I've seen this line of reasoning many times before and it needs to stop.
- School-Cotton 4y agoIndeed, but to be fair, Rust's smart pointers can be used to create memory leaks just as easily as C++'s. (Overall I think Rust is a much better language than C++, though).
- dxuh 4y agoThere was no way to implement a smart pointer in even a halfway usable and reliable way without move semantics, so C++11 is absolutely essential to use them well. Also I fully agree with the general sentiment. I have not produced a memory leak in many, many years in dozens of hobby projects or in a handful of professional C++ use. It's truly is a giant game changer. You can produce a leak with shared_ptr, but only if you do shit that looks dangerous and stinks to high heavens (a bit similar to the unsafe keyword).
- qalmakka 4y agoAs a long time c++ developer there's a big difference between when something shouldn't happen and when it can't happen. Rust makes certain classes of issues fundamentally impossible (ironically, leaks are possible in Rust), while in C++ it depends on how well you can enforce certain code guidelines on yourself and anyone that works on your same codebase. Also, you get like zero assurances that other people code has been written with the same quality standards as yours, as long as something is very easy to mess up, it will probably be inadvertantly messed up by someone.
- bayesian_horse 4y agoWhen rewriting a codebase there's a difference between 6 month's worth and a couple of years' worth.
- bsaul 4y agoi don't think joelonsoftware points apply here. - Their product is still relatively new (7 months of coding isn't that much) and not even released, - they picked a technology specifically designed for the problems they've identified on their existing codebase. - they completed the rewrite (and weren't stuck having to maintain the old codebase), and are happy with the result.
- Shorel 4y agoAgree. The risk is losing the current user base. For this particular software: No users, no market penetration, no risk at all doing a rewrite.
- steeleduncan 4y ago> since C++11 there is no reason for not using smart pointers There are many reasons for not using smart pointers, first amongst them for me being performance. Smart pointers do allow you to remove a large class of memory bugs from your code (albeit not memory leaks) in the same way that Rust's safe references do. However C++ smart pointers impose a run time performance penalty on your code, whereas in Rust the checks happen at compile time leading to better runtime performance.
- gpderetta 4y agoWhat's the overhead of an unique_ptr vs the equivalent rust pointer (yes yes, I know that the Itanium ABI has non optimal calling convention for unique ptrs, but I would be surprised if you can measure it)?
- deleted 4y ago[deleted]
- hdhrufjdi 4y agoJust a thought: null pointer check before deallocation
- gpderetta 4y agodelete of a null pointer is well defined.
- menaerus 4y agoAside from you being completely uninformed because free(nullptr) or, for that matter, delete nullptr does absolutely nothing and is well defined operation so you don't need to check for that condition in the first place. But even if you had to, what implications would it have, if you care to explain?
- hdhrufjdi 4y agoThe implications would be checking if it is null before performing the deallocation of the memory, which is a runtime overhead. Stack overflow says "delete" would check for null before deallocation: https://stackoverflow.com/questions/4190703/is-it-safe-to-delete-a-null-pointer https://stackoverflow.com/questions/4190703/is-it-safe-to-de... Happy to be educated
- doctor_eval 4y ago> I am specially concerned about throwing away months worth of code. Rewriting everything from scratch is what newbies love to do and will most likely get you in the same mess you were in. This was my first thought, but then I realised newbies would have started with Rust. :) In the first few months of a big build a huge amount of time and effort goes into the foundation: design, POCs, setting up environments, CI, testing infrastructure… My guess is that they weren’t very deep in production code, and the fact that they didn’t fall for the sunk cost fallacy speaks highly for them.
- pjmlp 4y ago> ....since C++11 there is no reason for not using smart pointers. Sadly there is, lack of security culture and plenty of devs won't allow them on a PR.
- pdimitar 4y agoNot allowing these in PRs is a thing?! Wow. Genuinely surprised.
- pjmlp 4y agoSee Orthodox C++.
- criddell 4y agoIn the context of this thread, why would somebody starting a new project be choosing between Orthodox C++ and Rust?
- pjmlp 4y agoTooling, existing ecosystem, built during 40 years of production deployment. Rust is naturally safer than C++, however there are still many domains where a bit of yak shaving is required before actually coding what one cares about. So it boils down to where to spend resources, and as note, I am definitly not a fan of Orthodox C++ ideas, rather having C++ improve its safety story as much as possible.
- Shorel 4y agoHaving seen C++20, anything less is just subpar. Orthodox C++ can be safely ignored by any sane developer.
- crabbone 4y ago> unreadable coding style And, again, people talk about it as if it was a real thing and they knew how to measure it... Also, C++ and Rust are very similar in appearance. So, I struggle to see how jumping ship here would be a big win.
- bakuninsbart 4y agoI'm quite nooby in both Rust and C++, but for the little interactions I had, I felt like Rust had a much clearer path forward than C++ when I was in doubt, and "how to write in good style" was more obvious. This leads me to the assumption that building a Rust culture is probably easier than building a C++ culture, because it is easier to get junior developers and those coming from other languages up to speed.
- dilawar 4y agoSame here. Clippy and rust compiler made me switch to Rust from c++. Now after experiencing cargo, I find python to be insufferable (tooling, not the language).
- josephg 4y agoYep. The one big beginner “mistake” I see people make in rust is overusing Box / String / Vec. Rust code that allocates everywhere can be even slower than javascript. The reason? Malloc is slower than you think. Slower than short allocations in V8 or Go. If you want performance, make friends with &str, &[], <I: Iterator<…>>, bumpalo, SmartString and SmallVec. (Or similar crates). Removing allocations from the hot path can improve performance by 10-100x. That said, most code isn’t a hot path. Performance doesn’t matter in most programs. And if you’re a veteran C++ programmer, none of this will come as a surprise.
- ZephyrBlu 4y agoI slightly disagree. Using heap allocated types is perfectly fine. The biggest thing I have to keep reminding myself coming from higher level languages is to re-use data structures, and to architect things in a way that this is possible. Allocating a new String/Vec every single time you do something is killer for performance, but if you do it once up front then clear the data structure for the next use it should be performant enough.
- criddell 4y ago> re-use data structures That's funny. I've been going mostly the other direction. I'm avoiding mutable structures whenever possible. I have a much easier time reasoning about stuff when I know that things aren't going to change mid-life.
- ZephyrBlu 4y agoThe argument for Rust is rarely that C++ cannot do the same task, it's that Rust provides better guardrails. Unreadable code is not a C++ specific problem, but does Rust make it easier to write readable code? Probably. Same for memory leaks and other similar problems.
- sidlls 4y agoNon-trivial Rust code can be just as unreadable as code one would write in any other language. In fact, some of Rust's features (e.g. lifetime identifiers, functional-ish constructs that people use to create huge call chains with closures everywhere) arguably make it easier to write unreadable code than one might find in other languages.
- deleted 4y ago[deleted]
- smolder 4y agoSome features do both: make it easier to write elegant code, while also making it easier to write unreadable code. Introducing such features is a trade-off and I think they generally choose wisely.
- blub 4y agoAs another commenter said: lifetime identifiers and functional constructs. To which I’ll add reference overuse. The C++ programmers that love over-complicated, read-only code would be right at home in Rust. In fact they’re probably working on it right now :-)
- mgaunard 4y agoRewriting stuff is actually quite good and expected of a startup. As the system grows, you realize all that was wrong with your previous version, and can write a new better one. That doesn't mean you need to switch to another language to do it though.
- odo1242 4y agoIt’s good from a technical perspective but not a business perspective. Startups only get a limited amount of time/money investment in order to prove their profitability. “Writing a better version” can come later, when the startup isn’t trying to come up with a version in the first place.
- mgaunard 4y agoStartups are tech businesses, they literally live and die by the quality of their tech. In particular for a product like this which is itself targeting developers.
- virtualritz 4y ago> * unreadable coding style: This is not a C++ problem. I would argue that it is, after a few years of Rust. My style in C++ was formed by my exposure to other people's code. I guess this is true for most people. Certainly, in C++, as well as in any language, Rust included, there are a myriad of ways to express yourself when solving a problem. Is my C++ coding style unreadable? I don't think so. But I used that language for 30+ years. Let's say I only used it for five years -- what then? I would have much less exposure to other people's code and hence to well written/readable code. Rust has rustfmt (a code formatter) and clippy (a very opinionated linter). And they get used lots. Most Rust CI now includes `cargo fmt --check` and `cargo clippy` runs than need to come out clean. This goes a long way in making code canonical. Clippy's amazing suggestions also made me a much better Rust developer in a much shorter time. Are rustfmt & clippy part of "Rust the language"? No. But in a way they are since there is nothing else they compete with for opinion on how Rust code should be formatted and written. When you onboard new people and they have adapted the pov that this makes lots of sense, it goes a long way in avoiding code being produced that is difficult to read for others. And because of this, I do indeed think that it is a problem of a programming language, in 2023, if the default tooling does not include such utilities. And a strong incentive through the community, pretty much all the available learning materials and repos in the wild, encouraging their use.
- bestouff 4y agoCame to say this exactly. C++ encountered coding styles are often a hodgepodge of "personal preferences" and urban legends. Rust coding style is partly enforced by rustfmt and clippy. The former makes you not worry about mixing styles into a project (after 30 years doing C/C++ I love this), the latter has really good suggestions which makes you reflect on your code.
- virtualritz 4y agoUsing a code formatter in C++ (e.g. via githook or the like) seems still the exception in most commercial C++ codebases I got to look at, when consulting in recent years. I.e. often there is a mix of styles, indentation/line wrap preferences and even the occasional tab in a codebase that otherwise uses spaces. Etc. etc. And that's just the formatting part. Linters seem to be mostly used manually by experienced developers but rarely are part of the commit pipeline or even if they are, their suggestions enforced. Your mileage may vary. I mostly look at code from a very specific industry. But I can't help but notice these things now, because of my exposure to Rust.