Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

To me the biggest difference between Rust and Zig in practical terms is that Zig does not offer statically safe resource management like Rust does, and as far as I know they have no intentions of doing so in the future because they think it’s less important than all this stuff about control flow. There are a lot of interesting ideas in the language but my disagreement with them on this issue is so fundamental that I don’t feel compelled to investigate it further.

Nonetheless I had gotten the impression from many posts on here before that Zig was a lot closer to finished than it really is, it seems like they’re not quite half way to something as polished as Rust 1.0. It is probably unfair to judge the language against Rust in its current state. Hopefully in a few years they will have figured out the memory safety problems and the stdlib documentation will stabilize more.



I think the comparison should be more nuanced and holistic than only memory safety, if it is to be a discussion on security and not theater.

For example, to get the conversation started, how do both languages compare in terms of checked integer arithmetic? Do they enable checked arithmetic by default in safe builds with an opt-out for performance, or do they leave default builds unsafe with an opt-in for safety?

Another example, JavaScript is 100% memory safe, does it follow that we can expect to see less exploits against NPM than C? Both ecosystems are massive, but I'd wager that most product release security teams are more stressed out about NPM than C dependencies right now. Not to say that they shouldn't be running C dependencies in sandboxes or be evaluating the risk of C (and remember that Zig is an order of magnitude safer than C, much closer to Rust actually, and more so in some areas). But NPM is probably getting more attention. Same thing for bug bounty issues reported. Probably more for NPM supply chain vulnerabilities than anything else. All 100% memory safety, and yet security is still a thing.

It's the many small decisions like these, along with thinking of security not as a binary extreme but as a probabilistic spectrum, that are more interesting to me.


> All 100% memory safety, and yet security is still a thing.

And nobody has ever claimed that memory safety is the only thing that matters with security, but it’s definitely high on the list. Can you imagine how much more of a nightmare NPM would be if JavaScript weren’t memory safe? This is the relevant counterfactual.

> Zig is an order of magnitude safer than C, much closer to Rust actually, and more so in some areas

Hard disagree. It’s definitely safer than C, (in terms of UB) but you can tell it’s not even close to Rust on a number of axes (yet?): https://scattered-thoughts.net/writing/how-safe-is-zig/

As for integer overflows, I don’t think they are nearly as big a security concern in a memory safe language with bounds checking. Feel free to correct me though.


> As for integer overflows, I don’t think they are nearly as big a security concern in a memory safe language with bounds checking. Feel free to correct me though.

See HeartBleed, CloudBleed, all buffer underflows resulting in buffer bleeds, letting someone read all your sensitive server memory, with no UAF.

They can also be caused just by integer overflow, which is what makes unchecked integer arithmetic so incredibly dangerous. It's easy for programmers to be oblivious to this, and overly rely on the borrow checker, thinking it can provide 100% memory safety, when by definition it can't.

And all kinds of software systems have these vulnerabilities. For example, I've worked on static analysis security software that could detect bleeds automatically in outgoing email attachments and it would find different bank systems leaking data in autogenerated statements.

From this experience, and from some bug bounty and security engagements I've done, I'm much more comfortable actually with Zig's approach to correctness and safety overall. I think the borrow checker is pretty awesome and has some serious muscle, but nevertheless Zig impresses me with its strict focus on explicitness, which I believe is the best approach still to eliminate these kinds of semantic gaps in general.

The borrow checker obviously can't protect you from bleeds (it can from some where static allocation is at play), but checked arithmetic would, or at least go pretty far — and again, it's about the spectrum, not the extreme.

It would be great for Rust to enable checked arithmetic by default for safety, with an opt-out for performance. Flipping this around would be a better default.


I feel like Nim is a much closer comparison than Rust. All three could be described as "grassroots projects on a holy mission to replace C and/or C++," but Nim and Zig are more similar in terms of operating budget/team size/adoption rate.

I may be a bit biased, but many of the problems mentioned in the post are the sorts of things I haven't dealt with in Nim for probably 2 years. Nim's error messages are still hit-or-miss and {.gcsafe.} still haunts me in my dreams, but the stdlib and language documents are great, and most of the annoying gotchas have been fixed.


Rust isn't on a holy mission; it's simply the only memory-safe language without a garbage collector.

It's really that simple. There is no international conspiracy behind Rust's popularity. It's the only thing that can do what it does in that respect.


Depends, I consider that Rust might succeed where Modula-2, Object Pascal and Ada failed, for anything else other than being a new generation of developers having a go at it.


There is nothing fundamental about ownership-based resource management, memory-safety can be achieved in other ways. Zig is C, it's not meant to abstract away memory management. You can do whatever in Zig, write a specialized allocator that's verified to be correct, even for a microcontroller with 2 KiB memory. Zig is a machine-oriented language, which means no hidden control flow, no hidden allocation. You can write a garbage collector or a compiler like Rust has too if that's what you need.


> memory-safety can be achieved in other ways

I mean, as far as achieving it at compile time, I would say it remains to be seen whether Zig's approach is one of these ways. There are certainly other known approaches, like the way ATS models pointers as proof objects, but these are also fairly abstract.

> Zig is C, it's not meant to abstract away memory management.

This is just hiding the ball though. Why don't we want abstractions on memory management? There is no runtime cost to providing the abstraction that Rust does. As such, "machine-oriented" is an ambiguous description of the difference here. The whole lesson of Rust is that there's nothing fundamental about the abstractions the machine itself provides, and we can create better abstractions without losing our orientation to those concerns.


> There is no runtime cost to providing the abstraction that Rust does.

This is technically true, but if I want to write a program that does not call malloc in its steady state, I can't use the stdlib or any library that uses the stdlib.


Herein lies the second biggest barrier to Rust's viability in embedded systems. (The first being that no microcontroller OEM ships libraries for Rust)


But this is not a fundamental limitation, there's nothing about the language that requires you to use heap allocation. That it contains affordances for safe heap allocation is a good thing, but you're not required to use them. There's always no_std and unsafe.


Here is an example with a keyboard firmware why you might not always want all that complexity.

https://kevinlynagh.com/rust-zig/

https://zig.news/aransentin/analysis-of-the-overhead-of-a-mi...

The point of languages like C and Zig is that they are only a bit higher level than assembly for portability, but otherwise they don't hinder you to do whatever. It's up to you to solve problems like memory safety. You might not even have a memory safety problem because you don't have memory in the first place, or your use case makes memory safety trivial.


I read the thread about the keyboard at the time. The author literally said it was a hobby project and they weren't concerned about safety, which is why they weren't interested in all of the solutions people offered for their problems with Rust. Zig's fine if you don't care about safety. But that's not really how I've heard it advertised.

> but otherwise they don't hinder you to do whatever

Neither does Rust! You can choose to ignore what the compiler wants you to do and just program with unsafe everywhere. The difference is that you don't have the option of writing safe code in Zig and C.

> It's up to you to solve problems like memory safety.

And so far, memory safety is not actually a problem that programmers have been able to solve by sheer force of will without borrow checkers or garbage collection. For a subset of trivial programs, sure. But not at any reasonable scale.


> nothing fundamental about ownership-based resource management, memory-safety can be achieved in other ways.

Not other ways. One other way. Just one. Garbage collection.



Thing is, if Zig is C, why bother at all, we already have C for it.


Zig is warts-free C, but you can use them together. You can gradually refactor your C codebase, Zig can even transpile C. Zig is also a standalone C toolchain, compiling and cross-compiling C is a breeze with it, and it has it's own libc implementation.


it does not have it's own implementation of libc, it just makes easier to work with implementations of libc and letting the cross compile, I think it was like that.

However a libc is a thing that zig probably wants and something I am also thinking on doing if I have the time


It doesn't fix C flaws like use after free, hardly warts-free.


That's not a C flaw, you can use an allocator that prevents use-after-free.

https://github.com/bwickman97/ffmalloc

The point of C and Zig is that they are low level and you can do whatever, like not use an allocator, or write an allocator.


Just like C memory debuggers for the last 30 years, so what is the benefit?


Defer, comptime, far better cross file model, yo name just a few things


For the price of an ecosystem with the same security flaws, hardly worth it.

Much easier to just use C+.


It's an open question [1] along with other safety checks both comptime and runtime [2]. The issue here is a balance of keeping language complexity low while providing safety at the same time and not depriving users of control when they know better than the type checker/lifetime analysis.

[1]: https://github.com/ziglang/zig/issues/782

[2]: https://github.com/ziglang/zig/issues/2301


> not depriving users of control when they know better than the type checker/lifetime analysis.

You're never deprived of control though, that's what unsafe is for, and it provides roughly the same level of safety as C or Zig would.


unsafe Rust has its own UB pitfalls that don't exist in C nor Zig, particularly in regards to the lifetimes of references [0] and preserving provenance through experimental apis [1].

[0]: the compiler is allowed to emit extra reads/writes to references so a mut and shared one to the same memory location cant be alive at the same time, across threads, and across sometimes non-obvious scoping rules.

[1]: [pointer::set_ptr_value](https://doc.rust-lang.org/std/primitive.pointer.html#method....) is used by containers like Arc for `from_raw` in order to carry over aliasing, mutability, and other location meta data.

unsafe Rust is also less ergonomic when dealing with concepts that go against the borrow checker like Pinning for intrusive memory, ptr::read/write and ManuallyDrop for controlling unorthodox object ownership/lifetime, and MaybeUninit/NonNull for facilitating certain data layout/access optimizations. Such designs often can't be wrapped in safe-Rust without introducing runtime overhead the patterns were used to originally avoid. Languages like Zig and C however make these patterns natural or event pleasant enough to consider it over unsafe Rust.


This is such a squishy value proposition, which is why people aren't taking Zig seriously.

Rust's value proposition is simple: no GC and no undefined behavior. Period. Nothing else has that.


I don't know, people like Mitchell Hashimoto and Tobi Lütke are taking Zig seriously for systems programming. Coil are also investing in writing a new distributed financial database for Zig—considering the trajectory of the language and the lifetime of our project, it made sense.

Of course the swell is early, but waves are what technology is about, and the surfers are there and paddling out. It's a great time to be getting involved, especially for greenfield projects that have some time in themselves to reach stability and don't want to pay a language compiler/complexity tax for the rest of the project's lifetime.

You could also throw a dart blindfolded into the Zig community and be pretty sure to hit some seriously talented programmers to learn from. If you're investing in a deep understanding of the language now, I'm pretty sure it will pay off down the line.



In terms of safety in systems programming, Zig is hardly better than something like Modula-2 or Object Pascal.

It just happens to have a better syntax for the C crowd.


Yeah, I've tried out zig and it's about at the point where Rust was when there were like 5 different pointer sigils and a GC was still included.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: