1. 19

  2. 8

    The TLDR is that the FixedBufferAllocator that Zig provides is fairly badly named. It’s a bump allocator that essentially doesn’t support deallocation (it has a super minor carve out for the very real free(alloc(...)) scenario that most general mallocs also used to track).

    While memory errors are an inherent problem of unsafe languages like Zig, in this particular case the “leak” is library issue. Happily this seems like something that can be fixed without breaking source compatibility, and as Zig is not an intended to be used as a system language (yet?) there aren’t any ABI issues to be concerned with increasing the size of the FixedBufferAllocator struct to have metadata to properly support deallocation. Of course the problem here is that existing users may be assuming bump allocation for perf or other reasons so it seems like fixing FBA should also include introducing BumpAllocator or some such.

    1. 3

      Zig is not an intended to be used as a system language (yet?)

      What do you mean by this?

      1. 2

        Zig hasn’t reached stable release yet. Andrew has stated that semver 1.0.0 will mark such a time. That doesn’t stop people from writing great software in Zig, e.g. River, Bun, etc but it does mean that major breaking changes could still occur.

        So I assume that because it’s not officially stable yet it’s likely not intended (in the strictest sense) to be used as a systems language yet (see aforementioned Bun, River etc showing people still using Zig to great effect).

        1. 2

          Sorry, I mean system language in the “as the OS provided API” sense. Step one of that is having a stable ABI that allows a binaries to be built targeting the system that doesn’t need to be rebuilt when the OS updates. The problem is that ABI stability isn’t something that is trivial to ensure - especially with many modern language features - so requires substantial amounts of engineering time that isn’t generally as fun as implementing new features.

          1. 2

            Zig has 0 problem exporting or consuming a C ABI.

            Furthermore, some operating systems such as Linux have a stable syscall ABI and do not even require usage of a stable language ABI.

            1. 1

              The operating system is not just the kernel ABI. It’s all of the system libraries. I get that there’s an expectation of rebuilding binaries for OS updates on linux and linux derived systems, but for others (windows, android - a linux derived system - the various Darwin systems) the assumption is recompilation is not needed.

              Zig doesn’t make an ABI stability guarantee I can see, and the comments in https://github.com/ziglang/zig/issues/3786 indicate even something as basic as the optional type has no guaranteed stable ABI right now. One of the comments goes so far as to say that they don’t think ABI stability is possible.

              To be a language that can be used to provide OS APIs (not just the kernel ABI) the language features must have a stable ABI, otherwise as noted in the above proposal the solution is for all libraries to just provide a C interface and then Zig binary calling a Zig library requires and unsafe transition into and out of C, losing the few Zig safety guarantees along the way.

      2. 3

        FixedBufferAllocator is intended to be used like a nongrowing arena. if you want to free arbitrary memory from a fixed size memory buffer, you can use the GeneralPurposeAllocator and back it with the FixedBufferAllocator.

        But really, what zig invites you to do is actually think about your memory allocation patterns. Then you realize that, for more than 90% of cases, a small collection of arena allocators is enough.

        1. 3

          I’m away from computer at the moment, so can’t check this for sure, but I think there are still cases where a GPA backed by an FBA will result in an OutOfMemory error. For example, if the GPA needs to expand the initially allocated space, and then frees in a different order. (Also, doesn’t GPA guarantee that addresses returned are not reused? I vaguely remember that being how it was implemented. In which case, it definitely will run out of space and won’t solve the problem).

          I mentioned it on the orange site that I think layering an ArenaAllocator over the FBA will do the trick as it frees in the opposite order to its allocations (it uses a singly linked list, so that’s the natural way to do it).

          1. 1

            I’m new to Zig. Do you have an example of a GPA backed by an FBA somewhere? Or: do you recommend any resource describing allocators with examples maybe? 🙇🏻‍♂️

          2. 1

            I hit the exact same problem. Thought fixed allocator actually freed arbitrary parts of itself. Nope! It taught me GPA is probably always the way to go.

            1. 1

              Yeah it’s a bad name. Something something the two hardest problems in computer science.