Live data from Hacker News

How (memory) safe is Zig? (2021)

scattered-thoughts.net

21–30 of 88 posts

Re: How (memory) safe is Zig? (2021)

#21
post #3

There is a third category of memory and other software safety mechanisms: model checking. While it does involve compiling software to a different target -- typically an SMT solver -- it is not a compile-time mechanism like in Rust. Kani is a model checker for Rust, and CBMC is a model checker for C. I'm not aware of one (yet!) for Zig, but it would not be difficult to build a port. Both Kani and CBMC compile down to…

Any good primers on SMT solvers?

Start with this.

https://smt.st/SAT_SMT_by_example.pdf

The algorithms behind SAT / SMT are actually pretty straight-forward. One of these days, I'll get around to publishing an article to demystify them.

Re: How (memory) safe is Zig? (2021)

#22

> it seems impossible to secure c or c++ False. Fil-C secures C and C++. It’s more comprehensively safe than Rust (Fil-C has no escape hatches). And it’s compatible enough with C/C++ that you can think of it as an alternate clang target.

> It's more comprehensively safe than Rust

Yeah. By adding a runtime.

> Fil-C achieves this using a combination of concurrent garbage collection and invisible capabilities (each pointer in memory has a corresponding capability, not visible to the C address space)

https://github.com/pizlonator/llvm-project-deluge/tree/delug...

Re: How (memory) safe is Zig? (2021)

#23
post #22

> it seems impossible to secure c or c++ False. Fil-C secures C and C++. It’s more comprehensively safe than Rust (Fil-C has no escape hatches). And it’s compatible enough with C/C++ that you can think of it as an alternate clang target.

> It's more comprehensively safe than Rust Yeah. By adding a runtime. > Fil-C achieves this using a combination of concurrent garbage collection and invisible capabilities (each pointer in memory has a corresponding capability, not visible to the C address space) https://github.com/pizlonator/llvm-project-deluge/tree/delug...

> Yeah. By adding a runtime.

So? That doesn't make it any less safe or useful.

In almost all uses of C and C++, the language already has a runtime. In the Gnu universe, it's the combination of libgcc, the loader, the various crt entrypoints, and libc. In the Apple version, it's libcompiler_rt and libSystem.

Fil-C certainly adds more to the runtime, but it's not like there was no runtime before.

Re: How (memory) safe is Zig? (2021)

#24
post #17
post #6

Earlier quoted context omitted.

What that means, though, is that you have a choice between defining memory unsafely away completely with Rust or Swift, or trying to catch memory problems by a writing a bunch of additional code in Zig.

What if -- stay with me now -- what if we solved it by just writing vastly less code , and having actually reusable code, instead of reinventing every type of wheel in every project? Maybe that's the real secret to sound code. Actual code reuse. I know it's a pipedream, but a man can dream, can't he?

Yeah that is the opposite take of recent posts that the Cargo/npm package dependence is way too heavy.

Saying we should rely on reusable modules is great and all, but that reusable code is going to be maintained by who now?

There's no sustainable pattern for this yet, most things are good graces of businesses or free time development, many become unmaintained over time- people who actually want to survive on developing and supporting reusable modules alone might actually be more rare than the unicorn devs.

Re: How (memory) safe is Zig? (2021)

#25
post #20

Earlier quoted context omitted.

I’d argue that ‘a bunch of additional code’ to solve for memory safety is exactly what you’re doing in the ‘defining memory safety away’ example with Rust or Swift. It’s just code you didn’t write and thus likely don’t understand as well. This can potentially lead to performance and/or control flow issues that get incredibly difficult to debug.

That sounds a bit unfair. All that code that we neither wrote nor understood, I think in the case of Rust, it’s either the borrow checker or the compiler itself doing something it does best - i.e., “defining memory safety away”. If that’s the case, then labeling such tooling and language-enforced memory safety mechanisms as “a bunch of additional code…you didn’t write and…don’t understand” appears somewhat inaccurate…

It is quite fair as far as rust is concerned. For simple data structures, like doubly linked list,are hard problems for rust

Re: How (memory) safe is Zig? (2021)

#26
post #22

Earlier quoted context omitted.

> It's more comprehensively safe than Rust Yeah. By adding a runtime. > Fil-C achieves this using a combination of concurrent garbage collection and invisible capabilities (each pointer in memory has a corresponding capability, not visible to the C address space) https://github.com/pizlonator/llvm-project-deluge/tree/delug...

> Yeah. By adding a runtime. So? That doesn't make it any less safe or useful. In almost all uses of C and C++, the language already has a runtime. In the Gnu universe, it's the combination of libgcc, the loader, the various crt entrypoints, and libc. In the Apple version, it's libcompiler_rt and libSystem. Fil-C certainly adds more to the runtime, but it's not like there was no runtime before.

It makes it a lot less performant and there is no avoiding or mitigating that downside. C++ is often selected as a language instead of safer options for its unusual performance characteristics even among systems languages in practice.

Fil-C is not a replacement for C++ generally, that oversells it. It might be a replacement for some C++ software without stringent performance requirements or a rigorously performance-engineered architecture. There is a lot of this software, often legacy.

Re: How (memory) safe is Zig? (2021)

#27
post #17

Earlier quoted context omitted.

What if -- stay with me now -- what if we solved it by just writing vastly less code , and having actually reusable code, instead of reinventing every type of wheel in every project? Maybe that's the real secret to sound code. Actual code reuse. I know it's a pipedream, but a man can dream, can't he?

Yeah that is the opposite take of recent posts that the Cargo/npm package dependence is way too heavy. Saying we should rely on reusable modules is great and all, but that reusable code is going to be maintained by who now? There's no sustainable pattern for this yet, most things are good graces of businesses or free time development, many become unmaintained over time- people who actually want to survive on developi…

I meant in programming in general, not specific to Rust or Cargo.

Re: How (memory) safe is Zig? (2021)

#28
post #2

> But it does not nearly approach the level of systematic prevention of memory unsafety that rust achieves. Unless I gravely misunderstood Zig when I learned it, the Zig approach to memory safety is to just write a ton of tests fully exercising your functions and let the test allocators find and log all your bugs for you. Not my favorite approach, but your article doesn't seem to take into account this entirely diffe…

Yes, testing is Zig's answer. But that quote is right. Testing doesn't achieve the same kind of systematic prevention of memory bugs that rust does. (Or GC based languages like Go, Java, JS, etc.).

You can write tests to find bugs in any language. C + Valgrind will do most of the same thing for C that the debug allocator will do for zig. But that doesn't stop the avalanche of memory safety bugs in production C code.

I used to write a lot of javascript. At the time I swore by testing. "You need testing anyway - why not use it to find other kinds of bugs too?". Eventually I started writing more and more typescript, and now I can't go back. One day I ported a library I wrote for JSON based operational transform from javascript to typescript. That library has an insane 3:1 test:code ratio or something, and deterministic constraint testing. Despite all of that testing, the typescript type checker still found a previously unknown bug in my codebase.

As the saying goes, tests can only prove the presence of bugs. They cannot prove your code does not have bugs. For that, you need other approaches - like rust's borrow checker or a runtime GC.

Re: How (memory) safe is Zig? (2021)

#29

Earlier quoted context omitted.

> Yeah. By adding a runtime. So? That doesn't make it any less safe or useful. In almost all uses of C and C++, the language already has a runtime. In the Gnu universe, it's the combination of libgcc, the loader, the various crt entrypoints, and libc. In the Apple version, it's libcompiler_rt and libSystem. Fil-C certainly adds more to the runtime, but it's not like there was no runtime before.

It makes it a lot less performant and there is no avoiding or mitigating that downside. C++ is often selected as a language instead of safer options for its unusual performance characteristics even among systems languages in practice. Fil-C is not a replacement for C++ generally, that oversells it. It might be a replacement for some C++ software without stringent performance requirements or a rigorously performance-e…

> a lot less performant

Is this just you speculating? How much is "a lot"? Where's the data? Let's get some benchmarks!

Re: How (memory) safe is Zig? (2021)

#30
post #6

Earlier quoted context omitted.

What that means, though, is that you have a choice between defining memory unsafely away completely with Rust or Swift, or trying to catch memory problems by a writing a bunch of additional code in Zig.

I’d argue that ‘a bunch of additional code’ to solve for memory safety is exactly what you’re doing in the ‘defining memory safety away’ example with Rust or Swift. It’s just code you didn’t write and thus likely don’t understand as well. This can potentially lead to performance and/or control flow issues that get incredibly difficult to debug.

> This can potentially lead to performance and/or control flow issues that get incredibly difficult to debug.

The borrow checker only runs at compile-time. It doesn't change the semantic meaning - or the resulting performance - of your code.

The borrow checker makes rust a much more difficult and frustrating language to learn. The compiler will refuse to compile your code entirely if you violate its rules. But there's nothing magical going on in the compiler that changes your program. A rust binary is almost identical to the equivalent C binary.

Post reply on HN