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