I’ve compiled you program and reproduced the segfault. I’ve looked at the disassembly, ran it in a debugger, checked the registers, but couldn’t figure out what it is.
So, my best guess, is that it’s eiter a miscompilation or you got a really well-hidden undefined behavior somewhere.
I think some code causes either state or previous to point to a temporary/local State variable that goes out of scope and thus pointers become garbage and start pointing to invalid memory addresses.
If valgrind and debugging doesn’t help, I would start printing and comparing pointer addresses, maybe adding more asserts.
Another thing that I would do (but might be unrelated) is to reduce the amount of default-initialized fields and instead use a named empty value with decl literals. And I would avoid using undefined for default values, instead set the value explicitly to undefined in places where it is valid. (To make sure that there is no place that forgets to set a field and lets it just default set to undefined)
I tried a bunch of things but I am also not sure whats going on, I don’t have the custom lldb-fork set-up, I don’t know whether that would show more.
The debugger shows a zero dereference but if you use any kind of temporary variable before the .file() then the code just ends up working, so that also makes me think it may be some kind of miscompilation, when code that should be equivalent, works.
I guess we need someone who is more used to looking at the assembly and can spot if something is wrong there.
Not necessarily related, but is there a reason you’re using inline so often? inline forces the function to be inlined, but Zig can also decide to inline the function on a regular function call.
I don’t think I use it that much, it’s mostly for one line fonctions that I use it.
There is a mother function for a specific task that calls “tool” functions which may be inline. To me this makes sense even thought I’m not sure it’s the best coding pattern.
Often I try to avoid inlining too much as it is the compiler’s task
diff --git a/src/position.zig b/src/position.zig
index 08f31ea..c0812ab 100644
--- a/src/position.zig
+++ b/src/position.zig
@@ -48,7 +48,7 @@ const CastleInfo = enum(u4) {
}
};
-pub const State = packed struct {
+pub const State = struct {
turn: Color = Color.white,
castle_info: CastleInfo = CastleInfo.none,
repetition: i7 = 0, // Zero if no repetition, x positive if happened once x half moves ago, negative indicates repetition
Still not sure why it was crashing, and it still seems like a miscompilation. However, I’m no longer surprised that it was crashing. Why are you putting a pointer into a packed struct? In general I would only put value or index types into a packed struct, otherwise I think packed structs are the wrong tool for the job.
~/tmp/packed_struct_ptr> zig run packed_struct_ptr_no_segfault.zig
1
1
Seems like some kind of alignment issue, where the u1 makes it an invalid size. It reminds me of this issue, but I don’t think the problems are actually related.
Well done!
And thank you, I’m using a lot of State objects so wanted to lower their memory footprint. I’ll be using packed struct for very specific ojects now, like for the Move one.
I let you create the ticket with the reduction if you think it’s worth it.
Yeah from the doc I knew I should avoid undefined, I’ll work on that too.