Search code examples
memoryzig

OutOfMemory in simple Zig use case


I'm learning Zig and i'm confused with an OutOfMemoryError.

In theory, the file that i'm trying to read has 9 bytes of size. The max_bytesparameter of readToEndAllocis setted to 9 but the problem i think is the FixedBufferAllocator.

If i don't set the fixed_alloc_buf to [2048]u8 or more then i have the out of memory error. If i try to run this code with [16]u8 then doesn't work:

const std = @import("std");

pub fn main() !void {
    const file = try std.fs.cwd().openFile("./file.txt", .{}); // file of 9 bytes
    defer file.close();

    var fixed_alloc_buf: [16]u8 = undefined; // boom if not [~2048]u8
    var fixed_alloc = std.heap.FixedBufferAllocator.init(&fixed_alloc_buf);

    var arena = std.heap.ArenaAllocator.init(fixed_alloc.allocator());
    defer arena.deinit();

    const allocator = arena.allocator();
    const buffer = try file.readToEndAlloc(allocator, 9);
    defer allocator.free(buffer);
}

Solution

  • Two things:

    • ArenaAllocator needs some memory for its own internal state.
    • And it also allocates more than you request. As it tries to keep the memory "chunked".

    In this case it tries to get 63 bytes from the parent allocator:

    const std = @import("std");
    
    pub fn main() !void {
        var gpa = std.heap.GeneralPurposeAllocator(.{ .verbose_log = true }){};
        defer std.debug.assert(gpa.deinit() == .ok);
        const allocator = gpa.allocator();
    
        var arena = std.heap.ArenaAllocator.init(allocator);
        defer arena.deinit();
    
        _ = try arena.allocator().alloc(u8, 9);
    }
    

    This prints:

    $ zig build run
    info(gpa): small alloc 63 bytes at u8@1e6234e0000
    info(gpa): small free 63 bytes at u8@1e6234e0000