简体   繁体   English

如何在 zig 中创建容器的 2d arrays?

[英]How to create 2d arrays of containers in zig?

I'm trying to alloc 2d arrays of HashMap(u32, u1) in Zig:我正在尝试在 Zig 中分配 HashMap(u32, u1) 的 2d arrays:

fn alloc2d(comptime t: type, m: u32, n: u32, allocator: *Allocator) callconv(.Inline) ![][]t {
    const array = try allocator.alloc([]t, m);
    for (array) |_, index| {
        array[index] = try allocator.alloc(t, n);
    }
    return array;
}

fn free2d(comptime t: type, array: [][]t, allocator: *Allocator) callconv(.Inline) void {
    for (array) |_, index| {
        allocator.free(array[index]);
    }
    allocator.free(array);
}

test "Alloc 2D Array" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = &gpa.allocator;
    defer _ = gpa.deinit();

    const HashSet = std.AutoHashMap(u32, u1);
    var array = try alloc2d(*HashSet, 4, 4, allocator);
    defer free2d(*HashSet, array, allocator);

    for (array) |_, i| {
        for (array[i]) |_, j| {
            array[i][j] = &(HashSet.init(allocator));
        }
    }
    defer {
        for (array) |_, i| {
            for (array[i]) |_, j| {
                array[i][j].deinit();
            }
        }
    }
}

However, when I test it, the debugger throw a seg fault.但是,当我测试它时,调试器会抛出一个段错误。

Can anyone tell me what is happening and how to fix it?谁能告诉我发生了什么以及如何解决它?

Thanks a lot!非常感谢!

I was having a look over your code and at first glance it seems to do what you're expecting;我正在查看您的代码,乍一看它似乎符合您的预期; I wasn't quite sure why you were passing a *HashSet rather than just a HashSet to your functions:我不太确定您为什么将*HashSet而不仅仅是HashSet传递给您的函数:

...

var array = try alloc2d(HashSet, 4, 4, allocator);
defer free2d(HashSet, array, allocator);

for (array) |_, i| {
    for (array[i]) |_, j| {
        array[i][j] = HashSet.init(allocator);
    }
}

... 

In fact, if you do that, everything works as you'd expect.事实上,如果你这样做,一切都会如你所愿。

That said, I couldn't see a reason why your version didn't work, so I had a poke at it, and found that what seems to be happening is that every single item in your array is being initialised with the same address, ie &(HashSet.init(allocator)) is returning the same address every time.也就是说,我看不出您的版本不起作用的原因,所以我戳了一下,发现似乎正在发生的事情是您的array中的每个项目都使用相同的地址进行初始化,即&(HashSet.init(allocator))每次都返回相同的地址。 I think this is why the deinit call is segfaulting, the memory is being freed multiple times.我认为这就是deinit调用出现段错误的原因,memory 被多次释放。

If you manually initialise every element in the array eg [0][0] = (HashSet.init(allocator)...etc everything seems to work. I'm not entirely sure what's going on here, but it might be that there's some kind of compiler optimisation at play, perhaps related to the way generics work. Hopefully someone else will come along with a better answer.如果您手动初始化数组中的每个元素,例如[0][0] = (HashSet.init(allocator)...etc一切似乎都可以正常工作。我不完全确定这里发生了什么,但可能是有某种编译器优化在起作用,可能与 generics 的工作方式有关。希望其他人能提供更好的答案。

Slightly unrelated, but a neat feature of Zig , you can iterate over a slice by reference which can sometimes be easier to read:有点不相关,但Zig的一个简洁功能,您可以通过引用迭代切片,这有时更容易阅读:

for (array) |*outer| {
    for (outer.*) |*item| {
        item.* = <something>
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM