Segmentation fault on `shrinkToLen`

Hello, i am having an issue where i am getting seg fault on a seemingly random spot of the code.

using a step debugger, the path to crash is

-> array_list.zig 1142:26
-> allocator.zig 360:18
-> allocator.zig 448:5
-> compiler_rt.zig 684:14

Segmentation fault at address 0x7f0d40580000
lib/std/mem/Allocator.zig:448:5: 0x12f89bf in free__anon_63085 (std.zig)
    @memset(bytes, undefined);
// i use 0,17.0 zig
// this function is run on a different thread
// allocator is debug allocator with `.thread_safe = true`
fn foo(allocator:std.mem.Allocator) ![2]std.ArrayList(T) {
    var lists: [2]std.ArrayList(T) = @splat(try .initCapacity(allocator, 10000));

    for (0..bounded) |index| {
      // bar adds items with assumeCapacity.
      bar(&works);
    }
   
   // always fails on this spot with a seg fault.
    for (&lists) |*m| {
        try m.shrinkToLen(allocator);
    }
    return lists;
}

The issue is splat evaluates the expression once and copies the result for each element, instead of evaluating the expression for each element.

That means both your array lists are operating on the same allocated memory, independently since they are different copies of their state.

Instead, you’d have to do something like the following:

var lists: [2]ArrayList(T) = @splat(.empty);
// above splat .empty makes this safe, `undefined` wouldnt be safe
errdefer for (&lists) |*list| list.deinit(allocator);

for (&lists) |*list| list.* =  try.initCapacity(allocator, 10000);
2 Likes

Thank you for your help.