Panic: incorrect alignment

I was trying to run MiniPixel. It didn’t compile with version of Zig I had installed. After fixing the compile errors and running it I got this error:

thread 751578 panic: incorrect alignment
/home/hallonsmak/src/MiniPixel/src/gui/Window.zig:154:44: 0x12a7b13 in handleEvent (minipixel)
    const mouse_event: *event.MouseEvent = @alignCast(@fieldParentPtr("event", e));
                                           ^
/home/hallonsmak/src/MiniPixel/src/main.zig:311:46: 0x123f67e in sdlProcessWindowEvent (minipixel)
                sdl_window.window.handleEvent(&enter_event);
                                             ^
/home/hallonsmak/src/MiniPixel/src/main.zig:734:51: 0x120df23 in sdlHandleEvent (minipixel)
        c.SDL_WINDOWEVENT => sdlProcessWindowEvent(sdl_event.window),
                                                  ^
/home/hallonsmak/src/MiniPixel/src/main.zig:872:31: 0x120c0f1 in main (minipixel)
                sdlHandleEvent(sdl_event);

In short the code basically looks like this:

const EventType = enum(u8) {
    Resize,
    MouseMove,
};

const Event = struct {
    type: EventType,
};

const MouseEvent = struct {
    event: Event,
    click_count: u32,
};

pub fn main() !void {
    var event = Event{ .type = .Resize };
    const e = &event;
    const mouse_event: *MouseEvent = @alignCast(@fieldParentPtr("event", e));
    _ = mouse_event;
}

I figure @alignCast is used incorrectly, i.e. only cast when the alignments are known to be compatible. But how can I know this? Can I assume that if both pointers are of the same type they will also have compatible alignments?

I have no experience with MiniPixel but given the code you provided, it seems the “event” passed into @fieldParentPtr doesn’t have the same alignment as it would have had if it had been a field of MouseEvent. It could be because the “event” in question isn’t a field of MouseEvent in this instance and the alignCast failed at runtime because of that. It would probably work if you pass in an Event that is actually a field of MouseEvent.

You could specify your own alignment for the result of @fieldParentPtr if you really, really want but is highly not recommended as the runtime error you received was a result of the event not being a field of a properly-aligned MouseEvent in the first place. Hence, mouse_event would not even be pointing to an actual MouseEvent.

    var event = Event{.type=.Resize};
    const e = &event;
    const mouse_event: *align(1) MouseEvent = @fieldParentPtr("event", e);
    _ = mouse_event;

Hope it helps!

2 Likes

Looking at the MiniPixel source code, it seems that they are calculating the fieldParentPtrs before checking if it’s even a valid MouseEvent:

    const mouse_event = @fieldParentPtr(event.MouseEvent, "event", e);
    const touch_event = @fieldParentPtr(event.TouchEvent, "event", e);
    switch (e.type) {
        .MouseMove, .MouseDown, .MouseUp, .MouseWheel => self.handleMouseEvent(mouse_event),
        .TouchPan, .TouchZoom => self.handleTouchEvent(touch_event),

This was fine before zig added the alignCast, but now this breaks because not all events have the required alignment of a MouseEvent.
The correct solution would be to only make the cast after the event type has been checked:

    switch (e.type) {
        .MouseMove, .MouseDown, .MouseUp, .MouseWheel => self.handleMouseEvent(@alignCast(@fieldParentPtr(event.MouseEvent, "event", e))),
        .TouchPan, .TouchZoom => self.handleTouchEvent(@alignCast(@fieldParentPtr(event.TouchEvent, "event", e))),
5 Likes

Thanks for the replies, cleared things up a bit. Yes, moving the casts to inside the switch fixes the issue, thanks.

I also just discovered there is a section about alignment in documentation. I somehow managed to miss it.

3 Likes