4 ms·
> Zig doesn't have the memory safety mechanisms of C++ level shared_ptr/unique_ptr. Zig's memory-safety is spatial, which is the more dangerous kind. Your exam
by pron 1y ago
> Zig doesn't have the memory safety mechanisms of C++ level shared_ptr/unique_ptr.
Zig's memory-safety is spatial, which is the more dangerous kind. Your examples are all temporal, and I don't know if I would call them "safety" as the language doesn't enforce or even encourage their use. For example, I work on one of the world's most foundational C++ projects (the HotSpot virtual machine), where neither shared_ptr nor unique_ptr are used at all; the language doesn't complain. There are reference-counted pointer libraries for Zig, too (although I don't think they're popular).
> It's essentially C's malloc/free with the added safety of defer
No, it isn't. First, unlike C or C++, it offers Rust-like spatial memory safety (again, the more important kind). Second, allocation in Zig is much more explicit than in C or C++.
> Besides, the way you trigger memory leaks in Rust/C++ is with circular references, which are much harder to create than just missing a free() somewhere.
They're also much harder to detect, especially when you have a very explicit memory allocation scheme.
> If you have memory that's not tied to a function scope's lifetime in Zig (or the scope of an allocator), then you're essentially have to go by C rules
Again, Zig doesn't seek to offer temporal memory safety, but it does offer the same level of spatial memory safety as Rust does, and while the "rules" of temporal management are similar to C, the way allocation works in Zig makes for a very different experience. An allocating function in Zig looks very different from its C counterpart.
Zig rejects the temporal memory management schemes of C, C++, and Rust - each for different reasons - and prefers a different kind. Of those, only Rust offers temporal memory safety (in the sense that it's controlled by the language) - albeit for a price - and the rest don't.
- torginus 1y agoI don't understand the distinction between spatial and temporal memory safety - from what I gather, spatial memory safety is just preventing out of bounds access of arrays, dereferencing uninitialized or otherwise invalid pointers. But use after free absolutely results in the same kinds of errors (accessing unused memory, or memory used by someone else). I also don't understand how one can sidestep the issue of ownership of memory - let's say you have a situation where a given piece of memory has changing or ambiguous ownership - like an event sent between two components, that has allocated some dynamic memory. I'm not saying this just because, I've encountered this exact issue before - many C libraries have event systems where the ownership is not obvious coming from the code - like the sender owns the event, and if you store a reference to it, then you have a dangling pointer if the sender decides to clean it up. That's why it's important to make it either obvious who owns what, or have some automatic system like GC or unique_ptr or the borrow checker. This is a very real issue and the only way you can fix it is to follow strong informal conventions the language has no way of enforcing or even communicating to the user. You mention Zig has a temporal memory management solution of a different kind - may I ask you what it is, because I haven't really seen it.
- pron 1y ago> But use after free absolutely results in the same kinds of errors (accessing unused memory, or memory used by someone else). That two bugs result in the same or similar outcome doesn't mean they're as common or as equally exploitable, which is why, in practice, it is distinctly a more dangerous weakness in the lists maintained by MITRE. > I also don't understand how one can sidestep the issue of ownership of memory It's not about side-stepping. There are many kinds of bugs in software, and while we'd like to avoid all of them, some problems are, in practice, more problematic. After all, Rust similarly "sidesteps" - as in doesn't prevent - all non-memory-safety-related weaknesses, some of which are more dangerous than dynamic memory safety. If Zig isn't good enough because it doesn't prevent temporal memory safety violations, then by the exact same logic, Rust isn't good enough because it doesn't prevent, say, injection vulnerabilities, that are more dangerous than temporal memory safety vulnerabilities. > I'm not saying this just because, I've encountered this exact issue before Sure, it's a real and serious issue. But injection is a more serious issue, which Rust doesn't prevent, and spatial memory violations are also a more serious issue, which Zig prevents just as Rust does. > That's why it's important to make it either obvious who owns what, or have some automatic system like GC or unique_ptr or the borrow checker. It is, but it's even more important to prevent code injection attacks, yet Rust doesn't do that. It all comes down to how much it's worth it to pay to prevent certain bugs. Rust was built because its designers believed that memory safety wasn't worth paying the higher memory footprint or the lower predictability of more popular memory-safe languages, or else there would have been no need for Rust in the first place. Similarly, it's just as reasonable to believe that the price you pay for temporal memory safety in Rust is not worth it. > You mention Zig has a temporal memory management solution of a different kind - may I ask you what it is, because I haven't really seen it. It's not a safe solution by any means (as the language doesn't enforce temporal memory safety, just as C++ doesn't), but memory allocation and deallocation in Zig is not the same as in C or C++. In particular, Zig functions that allocate are explicitly marked by having an Allocator parameter (https://zig.guide/standard-library/allocators/ https://zig.guide/standard-library/allocators/). Unlike in C, in Zig you know which functions allocate and using which allocator. That's how Zig is such a great fit for arenas. Because Zig is built around custom allocators, you can also choose allocators that offer use-after-free, double-free, and memory-leak protection, and do so selectively (unlike in C): https://sinclairtarget.com/blog/2025/09/getting-my-allocators-straight/ https://sinclairtarget.com/blog/2025/09/getting-my-allocator...