joadnacer / jdz_allocator

Zig General Purpose Memory Allocator
MIT License
29 stars 1 forks source link

Aligned allocation is broken #2

Closed Validark closed 2 months ago

Validark commented 2 months ago
const std = @import("std");
const jdz_allocator = @import("jdz_allocator");

const Allocator = std.mem.Allocator;

pub fn main() !void {
    var jdz = jdz_allocator.JdzAllocator(.{}).init();
    defer jdz.deinit();

    const gpa: Allocator = jdz.allocator();

    const overaligned_sizes = [_]usize{ 192, 3136, 192, 3136, 192 };
    var buffers: [overaligned_sizes.len][]const u8 = undefined;

    for (overaligned_sizes, &buffers, 0..) |overaligned_size, *buffers_slot, i| {
        std.debug.print("{}: {}\n", .{ i, overaligned_size });
        buffers_slot.* = try gpa.alignedAlloc(u8, 64, overaligned_size);
    }

    for (buffers) |buffer| {
        gpa.free(buffer);
    }
}

Gives the following error:

0: 192
1: 3136
2: 192
3: 3136
4: 192
thread 133011 panic: incorrect alignment
/home/niles/.cache/zig/p/122041a5792fa779a0aff08c1fb75e8ab847b8ec102666c309dd0fe07550d3249249/src/span.zig:93:38: 0x106cdfa in allocate (exe)
        self.free_list = @as(*usize, @ptrFromInt(block)).*;
                                     ^
/home/niles/.cache/zig/p/122041a5792fa779a0aff08c1fb75e8ab847b8ec102666c309dd0fe07550d3249249/src/shared_allocator.zig:97:37: 0x103c179 in alloc (exe)
                return self.allocate(aligned_block_size);
                                    ^
/home/niles/zig/0.12.0-dev.3630+215de3ee6/files/lib/std/mem/Allocator.zig:86:29: 0x106e574 in allocBytesWithAlignment__anon_6929 (exe)
    return self.vtable.alloc(self.ptr, len, ptr_align, ret_addr);
                            ^
/home/niles/zig/0.12.0-dev.3630+215de3ee6/files/lib/std/mem/Allocator.zig:211:40: 0x103d7ad in allocWithSizeAndAlignment__anon_4312 (exe)
    return self.allocBytesWithAlignment(alignment, byte_count, return_address);
                                       ^
/home/niles/zig/0.12.0-dev.3630+215de3ee6/files/lib/std/mem/Allocator.zig:205:75: 0x103898f in alignedAlloc__anon_3607 (exe)
    const ptr: [*]align(a) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address));
                                                                          ^
/home/niles/Documents/github/Zig-Parser-Experiment/src/jdzalloc_test.zig:17:46: 0x10385b7 in main (exe)
        buffers_slot.* = try gpa.alignedAlloc(u8, 64, overaligned_size);
                                             ^
/home/niles/zig/0.12.0-dev.3630+215de3ee6/files/lib/std/start.zig:511:37: 0x1038345 in posixCallMainAndExit (exe)
            const result = root.main() catch |err| {
joadnacer commented 2 months ago

Thanks for reporting this.

This issue can be reproduced more simply for const overaligned_sizes = [_]usize{ 192, 192, 192 };. It occurs due to utils.roundUpToPowerOfTwo erroneously rounding down, causing the aligned size for a len/alignment of 64/192 being 128 instead of 256 - with 3 consective allocations, this causes a segfault. This is fixed in https://github.com/joadnacer/jdz_allocator/commit/65372f6bff078fe32ac15359d35c06e3f60c07d8

While debugging this, I also noticed tests failing for max alignment on a device with a large page size (16KiB), as previously alignment was capped at the system's minimum page size. This is now fixed in https://github.com/joadnacer/jdz_allocator/commit/ecd8fd6d5677dd630f73cc397de1402fd9543c66, and alignment is now supported for up to 32KiB on all systems.