News for hackers. Stuff that matters.
Re:Zig's New Relationship with LLVM by skohan on Monday September 28, 2020 @10:19AM (#24616840)
I really like the Zig approach of improving the tooling for manual memory management rather than replacing manual memory management.

I think Rust is a great, worthy language, and for a lot of use-cases it makes sense to optimize for trying to just put everything on the stack, but there are a lot of other cases where what you really want to do is own allocation by yourself instead of trusting it to the compiler. I haven't tried Zig, but I really want to see if it can deliver on this.

Re:Zig's New Relationship with LLVM by dnautics on Monday September 28, 2020 @10:51AM (#24617235)
> I really like the Zig approach of improving the tooling for manual memory management rather than replacing manual memory management.

The new test allocator checks your code for memory leaks, use after free, and double free in a highly ergonomic fashion. I think is fantastic that zig encourages writing tests, and I think if you get full test coverage in your zig code with the test allocator, you will probably solve 99% of your memory errors.

I know this is possible in C++ (see alexandrescu's allocators talk from CppCon 2017?) But I would be surprised if anyone does it.

Re:Zig's New Relationship with LLVM by fanf2 on Monday September 28, 2020 @11:07AM (#24617441)
Address Sanitizer and valgrind are widely-used standard tools for finding allocation bugs
Re:Zig's New Relationship with LLVM by dnautics on Monday September 28, 2020 @05:20PM (#24621348)
I guess my feeling is that the tool chain for C/C++ is now C, C++, plus the preprocessor stuff (its own language), linker, make, (plus probably automake, cmake), gdb, valgrind, asan, etc etc etc, just to get "best practices/safe coding" right.

With zig, not 100% comparable (like not sure about gdb, but zig stacktraces and error traces are fantastic) it's all done in one language. Such a lowering of mental overhead and entry barrier!

The only thing you have to learn is that at comptime you get access to some magic (like the ++ operator)

Re:Zig's New Relationship with LLVM by setpatchaddress on Monday September 28, 2020 @12:36PM (#24618482)
They are very effective, but relatively difficult to use.
Re:Zig's New Relationship with LLVM by chubot on Monday September 28, 2020 @01:01PM (#24618787)
They're built into both GCC and Clang and very easy to use IMO.

The only hard part is figuring out how to pass -fsanitize=address into your compiler via your complex build system! And building with symbols.

That is inherent to the C/C++ toolchain and not a problem that sanitizers can address.

Re:Zig's New Relationship with LLVM by pron on Monday September 28, 2020 @08:20PM (#24622771)
Just to be clear, Zig isn't the same as C/C++ with sanitizers. Zig has slices and it doesn't have pointer arithmetic and pervasive casts. For example, if you preallocate a buffer and then reuse it, or chunk it into multiple pieces, sanitizers won't find an issue, but Zig will (thanks to slices). C simply has no way to express, "I want to pass a pointer into an array to this subroutine but it is only allowed to use n elements," when n is dynamic.
Re:Zig's New Relationship with LLVM by pjmlp on Tuesday September 29, 2020 @03:06AM (#24624897)
Re:Zig's New Relationship with LLVM by pron on Tuesday September 29, 2020 @06:46AM (#24626102)
Right, but in this case it's not a matter of what you have, but what you don't. Zig has slices as the only form of moving pointers around, and it doesn't have any pointer arithmetic. I.e. every time some data is traversed, the language ensures the size is known either at compile time or runtime.
Re:Zig's New Relationship with LLVM by pjmlp on Tuesday September 29, 2020 @07:38AM (#24626431)
Re:Zig's New Relationship with LLVM by pron on Tuesday September 29, 2020 @11:12AM (#24628767)
This isn't exactly pointer arithmetic as in C (or in unsafe Zig, as with @intToPtr, or using the "unknown size" pointer type, [*]). This is talking about preserving size information, and only when the arithmetic is compile-time-known; so it's more "array arithmetic".
Re:Zig's New Relationship with LLVM by pjmlp on Tuesday September 29, 2020 @01:06PM (#24630287)
Fair enough.
Re:Zig's New Relationship with LLVM by samatman on Monday September 28, 2020 @03:59PM (#24620673)
Sure but a language where "the only hard part" isn't a factor surely has a leg up on one where it is.

A lot of the advantage which Zig has over C is exactly in not having to support a towering edifice of tools and hacks which is older than I am. This is true to a significant degree of Rust and C++ as well.

Re:Zig's New Relationship with LLVM by pjmlp on Monday September 28, 2020 @01:00PM (#24618766)
On VS 2019, literally a checkbox away and rebuild.
Re:Zig's New Relationship with LLVM by whatshisface on Monday September 28, 2020 @10:23AM (#24616885)
Rust has manual allocation with Box<T>, it's just not as automatic as Zig. Rust's manual allocation pain is constant-factor overhead: typing out the type signatures takes longer every time you use it, but the complexity doesn't grow beyond that. I don't enjoy typing Box everywhere, but it's not that bad.

https://doc.rust-lang.org/std/boxed/index.html

Re:Zig's New Relationship with LLVM by skohan on Monday September 28, 2020 @10:31AM (#24616972)
Rust allows virtually any type of memory management you want, my point is the syntax is not optimized for things like arena-based memory management or custom allocators. Rust assumes most of the time you'll be passing around references to values or small structures allocated on the stack.
Re:Zig's New Relationship with LLVM by the_duke on Monday September 28, 2020 @10:47AM (#24617183)
In Zig, as far as I understand, you really just pass an allocator around. I don't see any special syntax to support this?

This could be done in Rust. There is, for example, the simple bump allocator bumpalo [1].

It would be nice if the the std collections supported this (in planning, but hasn't seen much progress), and most dependencies would not be built around a manually passed allocator.

> Rust assumes most of the time you'll be passing around references to values or small structures allocated on the stack.

Can you clarify what you mean here? All of the std collections (Vec, HashMap, etc) use allocation. There are also `Box`, `Rc` and `Arc`, which allocate and are used everywhere.

[1] https://github.com/fitzgen/bumpalo

Re:Zig's New Relationship with LLVM by skohan on Monday September 28, 2020 @11:05AM (#24617402)
Again, it's not about what you are able to do in Rust vs. Zig, it's essentially about the API of the language. Zig's semantics around memory management are imperative: i.e. you are telling the compiler when to allocate and deallocate memory. Rust's are declarative: you tell the compiler how the memory for a given value should be managed, and the compiler interprets these requirements to decide when memory should be allocated or deallocated.

Again, I do not think this a weakness of Rust, and I do not think it should change. In very many cases, the Rust approach is very helpful.

The point is there are also cases where imperative, explicit memory management is desirable.

Re:Zig's New Relationship with LLVM by the_duke on Monday September 28, 2020 @01:44PM (#24619281)
> The point is there are also cases where imperative, explicit memory management is desirable.

I agree that is the case, and Zigs convention of passing an allocator around and making those calls very explicit has merit.

I think you are over-estimating the amount of "magic" in Rust though.

The allocation-related logic is not part of the language or the compiler, but comes from the std (or alloc) crate. You just don't usually see a "malloc" call because it is hidden behind types in the standard library, which default to a global allocator. You still "manually" allocate by calling eg `Box::new()`.

The only magic is that Rust calls a destructor ( Drop::drop) when a value goes out of scope. Types can implement drop and use it to deallocate or decrement a reference counter. This is made possible by using an affine type system with lifetimes and move semantics.

This is conceptually not that different from doing something like `defer allocator.free(x)` in Zig, though less explicit.

ps: I realize that conventions make a difference. But nothing in Zig would stop me from having a global variable with an allocator, and using that without passing it around.

Re:Zig's New Relationship with LLVM by dnautics on Monday September 28, 2020 @07:25PM (#24622364)
> But nothing in Zig would stop me from having a global variable with an allocator, and using that without passing it around.

That's correct and you probably should do that in your own applications, but it will be frowned upon in libraries, and people will not choose to use them if you make that choice.

There's also another pattern, where you stuff a pointer to your allocator in your struct and have your "object" carry around its allocation system, you don't have to pass around allocators that way.

Re:Zig's New Relationship with LLVM by TylerE on Monday September 28, 2020 @12:27PM (#24618375)
The point is that the allocator CAN BE specified at call time for the entire stdlib.

And it doesn’t have to be just one allocator either, you can easily use multiple allocators simultaneously.

Re:Zig's New Relationship with LLVM by whatshisface on Monday September 28, 2020 @10:35AM (#24617030)
Yes, that's quite right. For many purposes, that's helpful encouragement, but sometimes you just want a reference.