| To be fair we are pushing up against the limits of my experience here. I'll do the best I can to address your points, but someone more experienced could probably do a better job. I don't think explicit use of allocators is distinct from memory leaks/safety. In Zig you will always know with 100% certainty that something is allocating memory. Making it easier to track what needs to be freed. This isn't always the case with C/C++. Also, as I said before, thanks to the way allocators work, Zig can provide a testing allocator which actively helps detect memory leaks. Their may be tools to help with this in languages like C/C++, but in Zigs case it's build right into the testing framework (which is also provided by the language). To your point about arenas, or other memory management techniques, it's not that they aren't possible in other languages. Obviously they are. But I think it's safe to say that the default memory management mechanism in C/C++ is malloc/free. This leads a lot of people down the path of lots of little allocs that all have to be tracked and paired with a call to free. In Zig, by design, any method that can allocate should take an allocator as an argument (or you pass one when the struct is created and it uses it, but this style is falling out of favor with the community). This pushes developers towards alternative methods of memory management, encouraging them to not just fall back on mallow/free. Arenas, fixed buffers, and other mechanism aren't just possible in Zig, they are first class citizens. I think there is a huge different between "defer" being part of the core language and being part of an extension. By being relegated to an extension it's usage is naturally going to be greatly reduced. The only two other languages I can think of that have this feature are Odin and Go, and Go is garbage collected. Yeah, in Zig you're directly manipulating pointers. That's just how the language is designed. It tries to make it safer, but it doesn't eliminate it, because it's not trying to. If you think this is a bad thing, that's fine. I'm not going to try to change your mind on that point. For nullability, everything you describe is opt in, and tool specific. It is baked into the type system in Zig the same way it is in Rust. It's just handle in (imo) a simpler and more straightforward way. Zig's errors as value approach isn't that much different from Rust's in spirit, and I think both Zig and Rust outclass anything in C++ in this regard. It's an option in C++, but mandatory in Rust and Zig, which I think is where the real power comes from. Ultimately, if you prefer Rust I'm not trying to change your mind. I was just trying to address your question. I don't think any of Zig's individual choices haven't been made in other languages, but I think the way Zig composes them all produces something novel and intriguing. All these little choices push developers in the right direction at every turn. Zig is still young, and it has plenty of rough edges to sand down, but I'm interested to see where it goes. Like I said previously, I think in the long run will see the average safety/correctness of Zig programs be on par with Rust's. I think the two will just fill different niches. |
I'm not trying to change your mind either; I'm just trying to understand the enthusiasm around Zig. There's a lot of it! To this day, I still don’t see what hard problems it would help me solve (that other languages make solving easier). At least for me, there’s little novelty or technical intrigue in that sense for any "systems" problem I've worked on.
- Explicit use of allocators: In my experience, hidden allocations rarely cause memory leaks. The real issues are forgetting to free memory, freeing the wrong pointer or managing overlapping objects. Some systems I’ve worked on also use different allocators or representations for the same types (e.g., for succinct encoding). Stronger type systems and optional automatic memory management make life easier when available.
- Arenas: malloc and free are as first-class as any other allocation mechanism in C. In C++, using alternative allocator types takes a bit more finesse. It’s an opt-in model rather than the default but still a relatively light lift.
- defer: I agree that its use would be significantly reduced but it’s easy to opt into. Many languages provide similar functionality either natively or through libraries, including Rust, C++, Python, C#, Java, D and Swift. Even C has this through GNU extensions (for fun, check out how far the Linux kernel takes this concept).
- Pointers: I love pointers but what helps performance more is explicit typing, stronger provenance and alias analysis.
While I'm not specifically advocating for Rust here, I don’t believe the average safety or correctness of a Zig program will match that of Rust. Rust is memory-safe by design, whereas Zig is not, and Rust also provides elegant solutions to several genuinely hard problems from memory management to events to scalable concurrency and an expressive type system.