Hey everyone, I am having an issue with understanding a memory leak I keep having with my implementation of a grid. I was trying to implement a “clone” method but it keeps having memory issues and I don’t understand how to fix it. Maybe someone here can help me out with understanding what I’m doing wrong.
const std = @import("std");
pub fn Grid(comptime T: type) type {
return struct {
const Self = @This();
allocator: std.mem.Allocator,
cols: usize,
rows: usize,
cells: []T,
pub fn init(allocator: std.mem.Allocator, cols: usize, rows: usize) !Self {
const cells = try allocator.alloc(T, cols * rows);
return .{ .allocator = allocator, .cols = cols, .rows = rows, .cells = cells };
}
pub fn deinit(self: *Self) void {
self.allocator.free(self.cells);
}
pub fn fromSlice(allocator: std.mem.Allocator, cols: usize, rows: usize, slice: []T) !Self {
std.debug.assert(slice.len == cols * rows);
const cells = try allocator.dupe(T, slice);
return .{ .allocator = allocator, .cols = cols, .rows = rows, .cells = cells };
}
pub fn clone(self: Self) !Self {
return try Self.fromSlice(self.allocator, self.cols, self.rows, self.cells);
}
pub fn inBounds(self: Self, col: usize, row: usize) bool {
return !(col >= self.cols or row >= self.rows);
}
pub fn getIdx(self: Self, col: usize, row: usize) usize {
std.debug.assert(row < self.rows);
std.debug.assert(col < self.cols);
return if (self.rows < self.cols) self.rows * row + col else self.cols * col + row;
}
pub fn get(self: Self, col: usize, row: usize) T {
return self.cells[self.getIdx(col, row)];
}
pub fn getPtr(self: Self, col: usize, row: usize) *T {
return &self.cells[self.getIdx(col, row)];
}
pub fn set(self: *Self, col: usize, row: usize, val: T) usize {
const idx = self.getIdx(col, row);
self.cells[idx] = val;
return idx;
}
};
}
// init test
test "grid init test" {
var g = try Grid(u8).init(std.testing.allocator, 2, 2);
defer g.deinit();
}
// from slice test
test "grid from slice test" {
var array = [_]u8{ 0, 1, 0, 1 };
var g = try Grid(u8).fromSlice(std.testing.allocator, 2, 2, &array);
defer g.deinit();
}
// grid clone test
test "grid clone test" {
var grid_list = std.ArrayList(Grid(u8)).init(std.testing.allocator);
defer {
for (grid_list.items) |*item| item.deinit();
grid_list.deinit();
}
var array = [_]u8{ 0, 1, 0, 1 };
var g = try Grid(u8).fromSlice(std.testing.allocator, 2, 2, &array);
defer g.deinit();
for (9..100) |_| {
const gc = try g.clone();
try grid_list.append(gc);
}
}