Live data from Hacker News

Safety: A comparaison between Rust, C++ and Go

nested.substack.com

161–170 of 188 posts

Re: Safety: A comparaison between Rust, C++ and Go

#161

Earlier quoted context omitted.

People have to consider race conditions anyway , they're part of our world. For example if you use git's ordinary --force to overwrite certain changes that's subject to a TOCTOU race, which is why force-with-lease exists. Even in the real world, I once opened a bedroom window to throw a spider out onto the garden below and a different spider came in through the window in the brief interval while it was open - exploit…

Is Rust really "fearless concurrency" ? Considering the number of deadlock issues encountered by folks using async Rust, I think "fearless concurrency" is misinformation by Rust evangelists. Deadlocks in production Rust microservice: https://blog.polybdenum.com/2022/07/24/fixing-the-next-thous...

While deadlock is undesirable, this is still behaviour which you can (and the author did) successfully reason about. You still have your consistent model of the world, in which you are deadlocked and can see exactly why.

"Fearless concurrency" isn't "It's impossible to make mistakes" it's only "The mistakes are no scarier than they were in your conventional non-concurrent program".

Re: Safety: A comparaison between Rust, C++ and Go

#162
post #9

Earlier quoted context omitted.

> Unless clang-tidy has false positives, in which case the comparison isn't apples to apples then. Confused... so you're suggesting Rust's checks are somehow free of false positives? Doesn't the halting problem get in the way? One Rust-specific example: https://www.reddit.com/r/rust/comments/nr7a33/is_the_borrow_...

There's a difference between code that used to compile no longer compiling because of an incorrect lint, and code that was never accepted. Rust is restrictive and gets less so over time. C and C++ need to become more restrictive over time, but that's a more traumatic direction.

> Rust is restrictive and gets less so over time. C and C++ need to become more restrictive over time, but that's a more traumatic direction.

I don't agree at all with your comment, and I find that sort of opinion miopic and not grounded on real-world software projects.

I 've worked on a fair share of legacy projects which were ported to the latest and greatest projects, including a couple of nightmare JavaScript ones. The very first thing we did was onboard onto static code analysis tools and source code formatters.

Once we enabled them we were faced with a big wall of red text dumps. With time that wall shrinked until there was no more red, and from thereon things stuck that way.

There was no trauma, only a kaizen approach to errors being flagged.

The whole C++ world already does this for decades, whether it's for compiler warnings, static code analysis, memory checkers, fuzzers, etc. What exactly leads you to believe this is traumatic?

Re: Safety: A comparaison between Rust, C++ and Go

#163
post #132

Earlier quoted context omitted.

The sibling says that C++ has the wrong defaults, full stop. Well in Rust the default `HashMap` uses a cryptographic hash, and you see it everywhere , it's the de facto community "default". In C++ the community "default" is `absl::flat_hash_map`/`folly::F14`, which use SIMD to compare a whole stripe of key-prefixes simultaneously. I want different defaults for different programs, but the idea that it's esoteric to ev…

In fact the crypto hash does not actually improve security. It is just slow. So, the trade is just: slow for nothing.

The (default) hash for Rust's HashMap and HashSet is a SipHash. People shouldn't call this a "cryptographic hash" or a "crypto hash" - that's misleading as it would lead you to think of algorithms like the SHA-2 family - but this is literally a cryptographic algorithm just one with very specific properties suitable for this task.

Such algorithms are crucial to avoid being subject to a Denial of Service attack which is, in fact, a security problem. Of course under the C++ "blame the programmer" philosophy you don't deserve protection from Denial of Service unless you knew you needed that and figured out how to ask for it properly.

Just as with the sort functions this is about safe defaults, not about constraining people who know what they're doing. Dropping in FNV instead of SipHash, or even using the identity function as a "hash", is not difficult if you are sure that's what you need.

Re: Safety: A comparaison between Rust, C++ and Go

#164

Earlier quoted context omitted.

I said ambivalent to hostile at worst, and I'm sorry, it is. I write FFI to C++ in Rust, Python, and Haskell practically every week, and Rust C++ sucks. Slap it in an `unsafe` block, fine. But let me move a `std::vector ` into my `unsafe` block easily. Erase the types, fine. But let me call `v.at(idx)`. Python takes C++ interop seriously, which is why Tensorflow and PyTorch and all the other people trying to script g…

I wouldn't say python takes C++ interop seriously, it's more like the pybind11 people are amazing at what they do and found a way to slice the problem neatly. But yes, it's night and day, pybind11 is a godsend.

Haha I don't know if it matters much whether we praise the `pybind11` folks in particular or the Python community in general or both: they are fucking amazing at what they do. It's such a hard problem that most language communities don't even seriously try, it's a nightmare to get even close on, and they get more than close. Everything just works exactly as you'd expect, with great performance (relatively speaking of course) into the bargain.

Top ten best open source language efforts on Earth. Maybe top five. Just legendary stuff.

I do think that for all its faults though (cough packaging cough), the Python community displays an incredible commitment to getting shit done and helping people solve their problems. It's really a rather mediocre language as these scripty things go, but it just friggin works, which is why everyone uses it for everything.

Re: Safety: A comparaison between Rust, C++ and Go

#165

Earlier quoted context omitted.

I think memory safety is the killer feature of rust, and has become so because people see the real world problem it's solving, more than through evangelicalism. We'll see in a few years when more "heavy shit" has been written/rewritten in rust. My prediction is that they will have significantly fewer memory safety issues than comparable c++ "heavy shit".

From where I sit the killer feature of Rust is that a bunch of amazingly cool software is written in it, especially in the terminal. I'm a big terminal guy, and I can't think off the top of my head of anything I use constantly that isn't written in Rust. `rg`, `fzf`, `zoxide`, `bat`, `viddy`, the list goes on and on, I fucking love the shit people are writing in Rust. And I think that should be the killer feature of…

Thanks for that list. I'd heard of rg and fzf but not the others.

I immediately thought: well what about Go for command line tools? Is this the viddy you speak of? https://github.com/sachaos/viddy If so, looks like it is written in Go. Looks like fzf too.

Re: Safety: A comparaison between Rust, C++ and Go

#166

Earlier quoted context omitted.

Rust isn't hostile about C++ interop, it's that between native interop (which requires dealing with templates and memory unsafety) and safety, Rust prioritized safety, while Carbon is trying the alternate approach. The behavior of C++ is simply hard to interface with while providing the assurances Rust gives you. Edit: how many languages have native C++ interop that supports the whole language? Would love to hear of…

It's not just C++ interop. We chose Zig because writing C library bindings for Rust is bewildering.

Yeah.

I know the talking points (it's impossible to go on the Internet and not know all the Rust talking points) but you have a few beers with some Rust people and pretty quickly you're hearing how anything that isn't Rust all the way down is somehow like, tainted, with the dreaded binary quality of being "unsafe" as opposed to "safe". A serious Rust hacker who shall remain nameless once broke out that old chestnut on me: "A barrel of wine and a spoonful of sewage makes a barrel of sewage." in reference to Rust software that links to C. It's not a coincidence that somewhere, every conceivable library that anyone could ever want is being rewritten in "pure Rust".

And it's a shame because Rust is fucking cool and I want to be using it even more than I already am. But I'm not going to become a Scientologist to get into a party in LA and I'm not going to throw away a mountain of excellent C and C++ because it's, unclean.

I'm optimistic that as Rust continues to have its center of gravity migrate away from strictly OSS and into ever higher stakes industrial settings (which it's clearly making great headway on) that the religious fervor will mellow and it'll become a "getting shit done" language that also happens to be a really cool language!

Re: Safety: A comparaison between Rust, C++ and Go

#167

Earlier quoted context omitted.

> a crashed program is a crashed program whether I dereferenced a null pointer or was poking around in a slice with multi-byte Unicode characters in it They aren't the same thing though, that's the point. Dereferencing a NULL pointer isn't guaranteed to crash. In fact if you are writing through the pointer, you may even have a security issue on your hands (rce, etc). Safe Rust may have runtime errors that "crash" the…

Yep, my favorite part of heap/stack corruption is not when it crashes immediately but rather when it rears its head 2-3 weeks/months later when some upstream call pattern or timing has changed. I've spend weeks chasing down single instances of this on multiple projects. The nasty part is you have no predictability in if it's going to be one that crashes immediately, silently writes garbage(hopefully not to disk!), is…

Yeah, this just isn't how it is anymore. The last time I was up shit creek because 50k boxes were crash looping and GDB couldn't get me a stack trace was in 2014. The last time I spent more than 30 minutes chasing a memory corruption issue was in like, 2018. And it was because some wise ass had decided to roll his own fibers by stomping on `rip`, `rbp`, and `rsp`.

These days you use `std::unique_ptr`, build with clang-tidy, CI under ASAN, and it's never an issue in practice. Once in a blue moon the CI chirps an ASAN failure that gives you the entire history of the memory address with line numbers and you fix the typo.

The safety that Rust gives me is that it's more expressive type system and modern affordances for things like exhaustive pattern matching lets me avoid logic errors, which are every bit as deadly as buffer overruns and much harder to mechanically identify.

It is usually easier to write correct code in Rust than in C++ because it's much more modern and frankly kind of an everyman's Haskell (which I mean as a compliment). But it's intellectually dishonest to say that this doesn't come at a cost: when you wander out of the borrow checker's sweet spot it can become kind of a Tetris puzzle even when you know all the rules on paper.

The same pattern matching that lets people see a borrow checker puzzle and immediately say "right, we need to do X" is the pattern matching that let's a C++ hacker see a failed template instantiation and immediately know what got misspelled.

Re: Safety: A comparaison between Rust, C++ and Go

#168
post #132

Earlier quoted context omitted.

In fact the crypto hash does not actually improve security. It is just slow. So, the trade is just: slow for nothing.

The (default) hash for Rust's HashMap and HashSet is a SipHash. People shouldn't call this a "cryptographic hash" or a "crypto hash" - that's misleading as it would lead you to think of algorithms like the SHA-2 family - but this is literally a cryptographic algorithm just one with very specific properties suitable for this task. Such algorithms are crucial to avoid being subject to a Denial of Service attack which i…

I clearly spoke out of turn when I mouthed off about Rust's table not defaulting to a Swiss design, and I thank you for straightening me out.

But to the degree that C++ has an RTFM vibe, and I really don't think you'll hear Andrei or Meyers or Sutter talking that way much, it's uniformly applied and not particularly partisan. In my experience C++ pros would rather be writing Haskell and that's where you get all these over-templated "header only" libraries.

Rust is in a glass house on "blame the programmer" stuff, because it's "blame the programmer for being dumb enough to not be using Rust exclusively".

The memory safety catechism makes sense for my SSH client, or web browser, or web server, or shell, or another few dozen security critical things. And frankly I'd feel safer if someone did a ground-up reimplementation of `bash` in Rust, I'd use it in a heartbeat. Tailscale writes their shit in Go for a reason, you don't want even the possibility of a use-after-free in your VPN.

But most of the software I run? It runs as me, and if someone is running as me behind the firewall, I'm in deep shit already.

`rustup` has `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` on the fucking home page, ditto vim/emacs extensions, etc. I'm calling bullshit on the every damned thing needs to be DoS or timing-attack hardened. It's marketing, and my original point is that all the other great modern features of Rust make a much better list of talking points.

Re: Safety: A comparaison between Rust, C++ and Go

#169

Earlier quoted context omitted.

> If it is so bad, it should (in the sense of how things would be in an ideal world) not compile. Yes, C++ can be a bad solution to a lot of problems, and that's okay. Use rust if you need a machine guarantee for memory safety (or you just like the language), you can use Go if you just don't care about that at all and want the language to take care of it. But you can use C++ for non-critical software that needs to be…

> Rust can be too much of a mental overhead than it's worth for some. Rust has the least mental overhead of any language I've ever used. The compiler literally takes all the mental overhead away.

> The compiler literally takes all the mental overhead away.

Increasing the strictness of the language has one effect: decreasing the number of potential solutions for a given problem.

If the restrictions are carefully chosen (like they are in rust) this leads to generally safer code. But don't fool yourself, the restrictions don't merely generate new solutions - they reject the ones that don't pass the tests.

A more extreme example is formal theorem provers. Carefully constructed proofs will take a lot of effort, but it will also make you confident that the code does what it needs to do.

The rust borrow checker is just a more restricted theorem prover that doesn't touch the logic, it just deals with the memory side of things. It's indeed very helpful in trying to explain what's wrong (and even suggest fixes), but it doesn't take the programmer overhead away.

In a more complex system rust inevitably makes it harder to come up with solutions. It will reject valid code just because it can't prove it's right, not because it's actually wrong. As a programmer, you're going to come up with such solutions, and while in time you get more used to writing code that rust likes, and rust too gets better at accepting correct solutions, you're going to have to fight the borrow checker sometimes.

I don't have a ton of experience with rust, but I encountered cases where equivalent C++ code would've worked just fine, but I had to change it because rust didn't like it.

Rust is an amazing language, but it definitely doesn't 'take all the mental overhead away'.

Re: Safety: A comparaison between Rust, C++ and Go

#170

Earlier quoted context omitted.

Yep, my favorite part of heap/stack corruption is not when it crashes immediately but rather when it rears its head 2-3 weeks/months later when some upstream call pattern or timing has changed. I've spend weeks chasing down single instances of this on multiple projects. The nasty part is you have no predictability in if it's going to be one that crashes immediately, silently writes garbage(hopefully not to disk!), is…

Yeah, this just isn't how it is anymore. The last time I was up shit creek because 50k boxes were crash looping and GDB couldn't get me a stack trace was in 2014. The last time I spent more than 30 minutes chasing a memory corruption issue was in like, 2018. And it was because some wise ass had decided to roll his own fibers by stomping on `rip`, `rbp`, and `rsp`. These days you use `std::unique_ptr`, build with clan…

I deal with issues like this about once a month. It may not happen where you work, but it definitely still happens.

If it really never happens where you work, consider yourself lucky.

Post reply on HN