I can declare a global general purpose allocator like:
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
const allocator = gpa.allocator();
and use it in a function to create an arraylist, perform a few operations, and return finally return the slice from it using toOwnedSlice.
However, when I change the function signature to additionally accept an allocator as an argument, the program doesn’t work.
I’m passing a testing.allocator
from a decltest and seeing memory leaks even when I defer the de-initialization of the arraylist.
I’m using zig version 0.14.0-dev.3237+ddff1fa4c
on Linux x86_64.
This is the program that I’m running zig test
on:
const std = @import("std");
const testing = std.testing;
// var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
// const alloc = gpa.allocator();
fn findAnagrams(alloc: std.mem.Allocator, s: []const u8, p: []const u8) ![]u8 {
if (s.len < p.len) {
return error.AnagramsCantForm;
}
var result: std.ArrayList(u8) = .init(alloc);
// defer result.deinit();
var freq_p: [26]u8 = @splat(0);
var window: [26]u8 = @splat(0);
for (0..p.len) |i| {
freq_p[p[i] - 'a'] += 1;
window[s[i] - 'a'] += 1;
}
if (std.mem.eql(u8, &freq_p, &window)) {
try result.append(0);
}
for (p.len..s.len) |i| {
window[s[i - p.len] - 'a'] -= 1;
window[s[i] - 'a'] += 1;
if (std.mem.eql(u8, &freq_p, &window)) {
try result.append(@intCast(i - p.len + 1));
}
}
return result.toOwnedSlice();
}
test findAnagrams {
const test_cases = [_]struct {
description: []const u8,
input1: []const u8,
input2: []const u8,
expected: []const u8,
}{
.{
.description = "substrings of p are present in s, and start at indices 0 and 6",
.input1 = "cbaebabacd",
.input2 = "abc",
.expected = &[_]u8{ 0, 6 },
},
.{
.description = "substrings of p start at indices 0, 1, and 2 in s",
.input1 = "abab",
.input2 = "ab",
.expected = &[_]u8{ 0, 1, 2 },
},
};
for (test_cases) |tc| {
const got = try findAnagrams(testing.allocator, tc.input1, tc.input2);
const want = tc.expected;
std.debug.print("{s}\n", .{tc.description});
try testing.expectEqualSlices(u8, want, got);
}
}