top | item 41718706

(no title)

soyyo | 1 year ago

Sorry if this is a silly question, i am a web developer so I dont usually dwelve into systems or low level programming except out of curiosity.

My understanting is that everyone is suggesting to move to memory safe languages when possible, however Zig does not seem to have any.

Since zig is a new language my guess is that the main use would be brand new projects, but sholdn't this be done in a memory safe language?

It seems that the selling point of Zig is: more modern than C but simpler than Rust, so I understand the appeal, but isn't this undermined by the lack of memory safety?

discuss

order

klabb3|1 year ago

> It seems that the selling point of Zig is: more modern than C but simpler than Rust, so I understand the appeal, but isn't this undermined by the lack of memory safety?

Memory safety is a useful concept, but it’s not a panacea and it’s not binary. If the end goal was safety JS would have been fine. Safe rust is guaranteed memory safe which is a huge improvement for system programming but not necessarily the end-all-be-all. There are always tradeoffs depending on the application. I personally think having safety be easily achievable is more important than guaranteed. The problems we’ve had with C and C++ is that it’s been hard to achieve safety.

audunw|1 year ago

In the areas where Zig really shines, the equivalent code in Rust would probably have a lot of “unsafe” keywords which basically disables the memory safety features anyway.

I think it remains to be seen if Zig is less safe than Rust in practice. In either case you have to write a lot of tests if you actually want your program to be safe. Rust doesn’t magically eliminate every possible bug. And if you’re running a good amount of tests in debug mode in Zig you’ll probably catch most memory safety bugs.

Still, if I was making something like a web browser I would probably use Rust

kibwen|1 year ago

> In the areas where Zig really shines, the equivalent code in Rust would probably have a lot of “unsafe” keywords which basically disables the memory safety features anyway.

This is a common misconception, but the `unsafe` keyword in Rust does not disable any of the features that enforce memory safety, rather it just unlocks the ability to perform a small number of new operations whose safety invariants must be manually upheld. Even codebases that have good reason to use `unsafe` in many places still extensively benefit from Rust's memory safety enforcement features.

flumpcakes|1 year ago

You can write very performant and very safe code in C/C++. Look at the gaming industry - or industry in general when things had to be burnt to disc. The problem now is that the complexity of the languages has increased and the average proficiency of software developers has plummeted (due in part to the increase in complexity). Google introduced Go to try and solve this, partly. Rust is another language that has memory safety as a core part of it's design. Another reason it is probably better are writing safer programs is that it is a lot less complex than C++. It seems to be catching up, but thankfully the memory safety concept is now deeply routed in the Rust community that even introducing complexity now, the language will still benefit from it's memory safety features and developers who are used to this style of language.

Zig is also a good choice if you care about safety - it simplifies things (by having a defer statement) and it's tooling is geared towards safety by having multiple targets that let you run your program in ways to catch memory safety issues during development. It is not enforced by the compiler, only at runtime in development/non-release-fast builds but still an improvement over C/C++.

int_19h|1 year ago

I really don't think the gaming industry can be used as a shining example of very safe C++ code. If there's any software category for which people have historically low expectations wrt bugs, including outright crashes, it's video games. Even back in the era when it was all shipped burned to disc, and Internet was a luxury, there were games that were literally unplayable at release for many players; remember Daggerfall?

wavemode|1 year ago

Not sure why Zig would be wholesale branded as being "memory unsafe". It has an extensive suite of tools and checks for memory safety that C does not have.

Safety is a spectrum - C is less safe than C++, which is less safe than Zig, which is less safe than Rust, which is less safe than Java, which is less safe than Python. Undefined behavior and memory corruption are still possible in all of them, it's just a question of how easy it is to make it happen.

pkolaczk|1 year ago

What makes you think Rust is any less safe than Java or Java less safe than Python?

jmull|1 year ago

> but isn't this undermined by the lack of memory safety?

IMO, partially. But zig isn't done, so we probably can't judge that yet.

Now, zig does have good memory safety. It's not at the level of Javascript or Rust, but it's not like C either.

Last I checked -- a while ago now -- user-after-free was a major issue in zig. IMO, that has to be addressed or zig really has no future.

Javascript really is a memory safe language. But its runtime and level of abstraction doesn't work for "systems programming".

For systems programming, I think you want (1) memory safety by default with escape hatches; and (2) a "low" level of abstraction -- basically one step above the virtual PDP-11 that compilers and CPUs have generally agreed on to target. That's to let the programmer think in terms of the execution model the CPU supports without dealing with all the details. And as a kind of addendum to (2), it needs to interop with C really well.

Rust has (1) nailed, I think. (2) is where it's weak. The low level is in there, but buried under piles of language feature complexity. Also, it disallows some perfectly safe memory management patterns, so you either need to reach for unsafe too often, or spend time contorting the code to suit the solution space (rather than spending time productively, on the problem space).

Zig is weak on (1). It has some good features, but also some big gaps. It's quite strong on (2) though.

My hope for zig -- don't know if it will happen or not -- is that it provides memory safety by default, but in a significantly more flexible way than rust, and maintains it's excellent characteristics for (2).

cweld510|1 year ago

Rust is more a response to C++ than to C. Both C++ and rust are big and complicated languages that are good for large projects that are performance-sensitive. Both have very strong static typing and can be verbose as a result.

C feels substantially different than Rust. It’s much smaller and less complicated. It’s technically statically typed, but also not in that it doesn’t really have robust non-primitive types. It’s a very flexible language and really good for problems where you really do have to read and write to random memory locations, rearrange registers, use raw function pointers, that sort of thing. Writing C to me feels a lot closer to Python sometimes than to Rust or C++. Writing algorithms can be easier because there is less to get in your way. In this way, there’s still a clear place for C. Projects that are small but need to be clever are maybe easier done in C than Rust. Rust is getting used more for big systems projects like VMs (firecracker), low level backends, and that sort of thing. But if I was going to write an interpreter I’d probably do it in C. Now, I’d do it in Zig.

pron|1 year ago

I understand why people compare Zig to C, being a simple low-level language, but I think that comparison is misleading. C++ is both more expressive than C and safer (when using appropriate idioms). Like Rust, Zig is as expressive as C++, and like Rust, Zig is safer than C++; it's just not as safe as Rust. Comparing Zig to other languages is difficult. While each of its features may have appeared in some other language, their combination, and especially the lack of certain other features, is something completely novel and results in a language unlike any other; it's sui generis.

However, unlike Rust Zig does reject C++'s attempt to hide some low-level details and make low-level code appear high-level on the page (i.e. it rejects a lot of implicitness), it is (at least on its intrinsic technical merits) suitable for the same domains C++ is suitable for. It's different in the approach it takes, but it's as different from C as it is from C++.

bvaldivielso|1 year ago

> but isn't this undermined by the lack of memory safety?

Yes, in my opinion, but from Zig's success you can see some people are willing to trade safety for a simpler language. Different people have different values

Though to be fair you can also use zig in old C projects, moving things incrementally. I don't know how many projects do that Vs greenfield projects though

melodyogonna|1 year ago

A lot of people, especially die hard C programmers, does not obsess over memory safety. They'll continue to start new projects in C, they're the ones being targeted by Zig.

jonathrg|1 year ago

Although it doesn't have the same level of compile-time guarantees, there are runtime checks to ensure memory safety if you use Debug or ReleaseSafe. You can do your development and testing in the default Debug mode and only use ReleaseFast or ReleaseSmall once you need the extra optimization and are confident in your test coverage.

bmacho|1 year ago

> Although it doesn't have the same level of compile-time guarantees, there are runtime checks to ensure memory safety if you use Debug or ReleaseSafe.

it is not very good, as

    const std = @import("std");
    const print = std.debug.print;

    fn foo() fn() *u32 {
        
        const T = struct {

            fn bar() *u32 {
                var x: u32 = 123;
                return &x;
            }

        };
        
        return T.bar;
    }

    pub fn main() void {

        print("Resultt: {}", .{foo()().*});

    }
outputs 123 in debug[0] and 0 in ReleaseSafe[1] instead of giving a Runtime Error.

[0] https://zig.godbolt.org/z/ezTr3zP6a

[1] https://zig.godbolt.org/z/3ExeveT69

DanielHB|1 year ago

Just wondering, if you don't care about that much about the performance for your application, is it okay to use the runtime checks compilation in production?

Like say I have a really weird issue I can't seem to find locally, can I switch my production server to this different compilation mode temporarily to get better logs? Can I run my development environment with it on all the time?

dns_snek|1 year ago

Zig isn't a memory safe language, but it does have memory safety features. Theoretically it's safer than C but isn't as safe as Rust.

For example, you can't overflow buffers (slices have associated lengths that are automatically checked at runtime), pointers can't be null, integer overflows panic.

renox|1 year ago

> integer overflows panic

Not in all the ReleaseFast mode where both signed and unsigned overflow have undefined behaviour.

And there's also the aliasing issue, if you have fn f(a:A, b: b:*A) { b = <>; which value has 'a' when f is called with f(a,a)? } (not sure about Zig's syntax).

That said I agree with your classification (safer than C but isn't as safe as Rust)

hansvm|1 year ago

I haven't yet seen a language where full memory safety didn't come at an extraordinary cost [0], and Zig is memory-safe enough to satisfy most programs' demands [1], especially if you shift your coding model to working with lifetimes and groups of objects rather than creating a new thing whenever you feel like it (which, incidentally, makes your life much easier in Rust and most other languages too).

[0] In Rust, a smattering of those costs include:

- Explicit destruction (under the hood) of every object. It's slow.

- Many memory-safe programs won't type-check (impossible to avoid in any perfectly memory-safe language, but particularly annoying in Rust because even simple and common data structures get caught in the crossfire).

- Rust's "unsafe" is only a partial workaround. "Unsafe" is in some ways more dangerous than C because you don't _just_ have to guarantee memory safety; you have to guarantee every other thing the compiler normally automatically checks in safe mode, else your program has a chance of being optimized to something incorrect.

- Even in safe Rust, you still have a form of subtle data race possible, especially on ARM. The compiler forces a level of synchronization to writes which might overlap with reads, but it doesn't force you to pick the _right_ level, and it doesn't protect you from having to know fiddly details like seq_cst not necessarily meaning anything on some processors when other reads/writes use a different atomic ordering.

- Even in safe Rust, races like deadlocks and livelocks are possible.

- The constraints Rust places on your code tend to push people toward making leaky data structures. In every long-running Rust process I've seen of any complexity (small, biased sample -- take with a grain of salt), there were memory leaks which weren't trivial to root out.

- The language is extraordinarily complicated.

[1] Zig is memory-safe enough:

- "Defer" and "errdefer" cover 99% of use-cases. If you see an init without a corresponding deinit immediately afterward, that's (1) trivially lintable and (2) a sign that something much more interesting is going on (see the next point).

- In the remaining use-cases, the right thing to do is almost always to put everything into a container object with its own lifetime. Getting memory safety correct in those isn't always trivial, but runtime leak/overflow detection in "safe" compilation modes go a long way, and the general pattern of working on a small number of slabs of data (much like how you would write a doubly-linked list in idiomatic Rust) makes it easy to not have to do anything more finicky than remember to deallocate each of those slabs to ensure safety.

DanielHB|1 year ago

From my point of view the main point of memory safety is not to avoid bugs (although it helps with that) is that when you do have a memory management bug you don't risk remote code executions or leaking sections of memory to attackers (private keys and such).

flumpcakes|1 year ago

I agree with all of your points, and think Zig is perfectly workable. I think for big enterprise software, being written by teams from dozens to hundreds, that Rust probably is a better choice. It would certainly be faster than shipping more electron apps.

vlovich123|1 year ago

There’s a lot to criticize about Rust for sure, but I feel like some of the points here aren’t necessarily in good faith.

> Explicit destruction (under the hood) of every object. It's slow.

Care to actually support this with data? C++ is quite similar in this respect (Rust has a cleaner implementation of destruction) and generally outperforms any GC language because stack deallocation >> RC >> GC in terms of speed. There’s also a lot of good properties of deterministic destruction vs non deterministic but generally rust’s approach offers best overall latency and throughput in real world code. And of course trivial objects don’t get any destruction due to compiler optimizations (trivially live on the stack). And zig isn’t immune from this afaik - it’s a trade off you have to pick and zig should be closer since it’s also targeting systems programmers.

> - Many memory-safe programs won't type-check (impossible to avoid in any perfectly memory-safe language, but particularly annoying in Rust because even simple and common data structures get caught in the crossfire).

Actually most memory safe languages don’t have issues expressing data structures (eg Java). And rust has consistently improved its type checker to make more things ergonomic. And finally if you define rust as language + stdlib which is the most common experience those typical data structures are just there for you to use. So more of a theoretical problem than a real one for data structures specifically.

> Even in safe Rust, you still have a form of subtle data race possible, especially on ARM.

I agree that for the language it’s weird that this is considered “safe”. Of course it’s not any less safe than any other language that exposes atomics so it’s weird to imply this as something uniquely negative to Rust.

> Even in safe Rust, races like deadlocks and livelocks are possible.

I’m not aware of any language that can defend against this as it’s classically an undecidable problem if I recall correctly. You can layer in your own deadlock and livelock detectors that are however relevant to you but this is not uniquely positive or negative to rust so again weird to raise as a criticism of Rust.

> The constraints Rust places on your code tend to push people toward making leaky data structures. In every long-running Rust process I've seen of any complexity (small, biased sample -- take with a grain of salt), there were memory leaks which weren't trivial to root out.

I think you’re right to caution to take this with salt. That hasn’t been my experience but of course we might be looking at different classes of code so it might be more idiomatic somewhere.

> In the remaining use-cases, the right thing to do is almost always to put everything into a container object with its own lifetime

You can of course do that with Rust boxing everything and/or putting it into a container which reduces 99% of all lifetime complexity. There are performance costs of doing that of course so that may be why it’s no considered particularly idiomatic.

My overall point is that it feels like you’ve excessively dramatized the costs associated with writing in Rust to justify the argument that memory safety comes with excessive cost. The strongest argument is that certain “natural” ways to write things run into the borrow checker as implemented today (the next gen I believe is coming next year which will accept even more valid code you would encounter in practice although certain data structures of course remain requiring unsafe like doubly linked lists which should be used rarely if ever)

anacrolix|1 year ago

You can build with runtime checks that help find all the issues. It's suprisingly effective, probably more effective than actually doing it in the type system.

zoogeny|1 year ago

> everyone is suggesting to move to memory safe languages when possible

Be careful not to believe your own hyperbole. Some people are loudly and persistently recommending other people to use memory safe languages. Rust may be quite popular lately but the opinions held by some subset of that community does not reflect the opinions of "everyone". It would be just as silly to say: "everyone is suggesting to move to OSS licenses".

> sholdn't [... new projects ...] be done in a memory safe language

Again, please be careful to understand where you are getting this "should". What happens exactly if you don't choose a memory safe language? Will the government put you in jail? Or will a small vocal community of language zealots criticize you.

Maybe you feel like you want to fit in with "real" programmers or something. And you have some impression that "real" programmers insist on memory safe languages. That isn't the case at all.

In my experience, making technical decisions (like what programming language to use) to avoid criticism is a really bad path.

andrewstuart|1 year ago

Zig aims for simplicity.

Rust is deeply complex.

AlienRobot|1 year ago

Yeah, but Rust is undermined by its syntax.

I don't want to write Rust. I want to write Zig. It's like Python, but blazingly fast.

3836293648|1 year ago

It really isn't. It's undermined by all the metadata you need for its safety model and that's a part of the semantics. You cannot create an alternate grontend for rust that gets rid of all the parts people hate