Live data from Hacker News

Unsafe Zig Is Safer Than Unsafe Rust

andrewkelley.me

81–90 of 105 posts

Re: Unsafe Zig Is Safer Than Unsafe Rust

#81
post #64
post #60

Earlier quoted context omitted.

Container and iterator code is not safe at all since there is no bounds checking by default and no protection against iterator invalidation, which can both cause writes to memory outside the intended object and thus a catastrophic outcome. There is no safe subset of C/C++ unless you just don't use pointers or references at all (and refrain from using any library that is not safe which includes large parts of the stan…

To be fair, I believe you and the individual you are replying to are treating the word 'safe' differently. Correct; C++ doesn't have a built-in concept of "safe" that is compiler guaranteed and anything written in that, if it isn't written defensively at literally every line of code , falls on the library consumer to handle that. Rust, CLR/JVM/interpreted languages are 'safe' because the compiler will flat out refuse…

Reliable is a better word. C++ has lots of features to help you avoid accidents. It's just that you know that certain operations take certain levels of precautions. I like C++. I like the expressiveness it provides. Yes, some things are unsafe, but the amount of time I've spent finding segfaults or other memory errors since becoming proficient is an epsilon in relation to the amount of time I've spent getting all of my crazy template magic to fit into the right spots.

Re: Unsafe Zig Is Safer Than Unsafe Rust

#82
post #75

Earlier quoted context omitted.

> ...is obviously safely composable with any other safe Rust code precisely because it obeys safety guarantees when transitioning from unsafe to safe. And what are those safety guarantees? This is the part where I see a lot of handwaving. > ...either R + X + Y is safe or one of [X, Y] has a safety bug and is inaccurately marking an unsafe interface as safe. Correct, but the problem is that we don't have a way to iden…

> And what are those safety guarantees? This is the part where I see a lot of handwaving. I think this is the contention: correct me if I'm wrong, but you're saying, that, in practice, the safety guarantees of Rust are currently too nebulous to be able to be enforced reliably, whereas most other people in this thread are, I think, visualising the "platonic Rust"/post-RustBelt Rust where the currently vague conditions…

I think this is a good point, thank you. Will be remembering to tease this out in the future!

Re: Unsafe Zig Is Safer Than Unsafe Rust

#84
post #62

Earlier quoted context omitted.

C++ largely suffers from the same problems. Often a C++ programmer can write code which relies on iterators and containers which is quite safe and difficult to mess up, while for a variety of highly-specialized applications, mixtures of packed structs, pointer arithmetic, and arbitary sequences of binary data need to be handled with utmost care. Knowing when to use which set of tools and how to safely glue them toget…

I'll be an anti-crustangelist and say that I've actually avoided moving a C++ project I've been working on over to Rust because (1) I'm finding that fixing some of the previous code's pre-C++xx practices is suitable enough and (2) I've only written a few small things in Rust up to this point and learning the 30% or so more that I'd need to in order to get things fixed would take more time and has more unknowns. Grant…

Well, if you want to write a tree using indices in a local array instead of pointers for better locality and memory footprint (which is ideal for many situations), you run into the difference between language pointers and computer science pointers. That's not even something that Rust will be smart enough to help you do properly.

Re: Unsafe Zig Is Safer Than Unsafe Rust

#85
post #76

I think the Rust is not how you should write such a code. Why not start with the struct, and cast to a void* or a char* when C code requires it? I.e., the buggy example becomes: #[derive(Copy, Clone, Debug)] #[repr(C)] struct Foo { a: i32, b: i32, } fn main() { let mut array = [Foo { a: 0x01010101i32, b: 0x01010101i32 }; 256]; let foo = &mut array[0]; foo.a += 1; } The unsafe section isn't even required, and the effe…

While the approach you suggest usually works well, it doesn't in this case: FILE_NAME_INFO[1] uses a "flexible array member"[2] (although not the C99 version of it), of requiring a dynamically sized character array in the struct's allocation, and writing directly to the memory after a struct instance. The 'WCHAR FileName[1];' field at the end of the struct is just a placeholder to allow easy access to that character…

Ugh. You're absolutely right. I never liked those even in C.

So, it seems like this is relative easy to do on the stack, which is how the example does it presently. See the link below to my attempt; the stack allocation is still all safe code, still a single line. However, I presume that one will want to also create one on the heap, especially since in the example the author poses it would be a rather large stack allocation, and one might — quite reasonably — put that on the heap.

My attempt is here: https://play.rust-lang.org/?gist=1c50b35941506316372da860cae...

Couldn't avoid the unsafe for that, but, I was able to get rid of the transmute call, and transmute is a function where the warning on the tin is "this function is not just unsafe, it is radioactive". But the amount of code required still felt a bit lacking.

It seems these are an area of active work[1][2] currently.

I think there is still definitely a valid point that the author is hitting — that encoding more information into the program can allow the compiler to catch more classes of errors. (This is, after all, the very logic that gave us Rust.)

[1]: https://github.com/rust-lang/rfcs/pull/1909

[2]: https://github.com/rust-lang/rust/issues/18806

Re: Unsafe Zig Is Safer Than Unsafe Rust

#86
post #57

I think both "as" and using "transmute" for non-exceptional circumstances are mistakes in Rust. There should instead be a bunch of type-specific cast operators that can check things like alignment and that what you intended to be a zero-extending integer cast is not in fact truncating to a smaller integer type, and so on. It's not too late to deprecate "as" and discourage using "transmute" in favor of those.

This isn't about transmute or having a specific operator that checks alignment. The point is that the alignment is part of the type is zig and, to a lesser degree, it's about having the comptime machinery for zig to decide, when you offset a &align(4) u8 by an expression, whether the result should have type &align(1) u8, &align(2) u8, or &align(4) u8.

Re: Unsafe Zig Is Safer Than Unsafe Rust

#87
post #33
post #20

Earlier quoted context omitted.

Rust's approach to "unsafe" is to let the programmer do whatever they want. Having to use this for UNIX-type API calls is kind of lame. I once proposed extending C to allow talking about array sizes.[1] You'd define "read" as int read(int fd, char &buf[len], size_t len); The compiler now knows that "buf" is an array with length "len", and can check calls for "buf" being the right size. The generated code for the call…

> Rust's system for external C calls should be more like that and less about casts to raw pointers. It seems a rosy-eyed view to think that this would helping safety significantly, and would require a lot of effort: it's likely to be much lower pay-off than other things, like investing in, say, sanitizers or even just doing the work of writing safe wrappers for popular C libs, removing C FFI concerns from most people…

Of course you want to use Rust slices. Those map directly to the kind of C array I outlined. If you could declare a C API that way to Rust, you'd get the mapping without talking about pointers explicitly at all.

What I'm arguing for is a declarative way to talk about C interfaces that is consistent with Rust's model. This is better than using "unsafe" to construct C-type raw pointers. Yes, this is more restrictive and there will be some awful C APIs you can't describe. That's a good indication said C API is trouble.

Re: Unsafe Zig Is Safer Than Unsafe Rust

#89
post #32
post #26

Zig looks very interesting. There is only TODO in memory section in documentation. From what I understand there is only manual memory management? I've seen there is a mention about custom allocators, any details? Any RAII like concept? or full manual memory management?

"Zig does not support RAII or operator overloading because both make it very difficult to tell where function calls happen just by looking at a function body." more in the 0.1.1 release notes! http://ziglang.org/download/0.1.1/release-notes.html "Zig's standard library is still very young, but the goal is for every feature that uses an allocator to accept an allocator at runtime, or possibly at either compile time or…

>"Zig does not support RAII or operator overloading because both make it very difficult to tell where function calls happen just by looking at a function body."

How about showing an error if you don't call the deconstructor manually?

Re: Unsafe Zig Is Safer Than Unsafe Rust

#90
I find it so funny people are so fixed on bounds checking. A minimal run time environment is good. It's easier to port and runs faster. Further, there are more issues than bounds checking.

Also a big part of it is companies don't really pay for quality software. They just care about software that works mostly made to cost. I don't see rust reducing this cost much except. First, one still has to interact with hardware, that does not fit rust's/zig's/(insert safe language) run time model. Secondly, soon as you start interacting with software out side of that model same issues apply.

Post reply on HN