Cannot fix memory leak in this code. Can you help me please?
The function generates a simple string by the length specified in the argument, using the allocator passed through the arguments
const std = @import("std");
pub fn randomString(allocator: std.mem.Allocator, size: u32, charset: []const u8) ![]const u8 {
if (size == 0) {
return error.InvalidSize;
}
if (charset.len == 0) {
return error.InvalidCharset;
}
const buffer = try allocator.alloc(u8, size);
defer allocator.free(buffer);
var prng = std.rand.DefaultPrng.init(blk: {
var seed: u64 = undefined;
try std.posix.getrandom(std.mem.asBytes(&seed));
break :blk seed;
});
var rand = prng.random();
for (buffer) |*ch| {
const idx = rand.int(u64) % charset.len;
ch.* = charset[idx];
}
const result = try allocator.dupe(u8, buffer);
return result;
}
As far as I understand from the logs, the leak occurs after allocator.dupe in the code, but I try to remove it, then the memory leak occurs in the buffer variable.
Test logs:
Test [1/1] string.test.should generate random string with specified charset... [gpa] (err): memory address 0x102584010 leaked:
/opt/homebrew/Cellar/zig/0.12.0/lib/zig/std/mem/Allocator.zig:319:40: 0x1024794a3 in dupe__anon_3182 (test)
const new_buf = try allocator.alloc(T, m.len);
^
/Users/kitanoyoru/Code/fun/zig/z/src/string.zig:27:38: 0x102478a77 in randomString (test)
const result = try allocator.dupe(u8, buffer);
^
/Users/kitanoyoru/Code/fun/zig/z/src/string.zig:41:32: 0x1024796f7 in test.should generate random string with specified charset (test)
const result = randomString(allocator, size, charset) catch |err| {
All 1 tests passed.
1 errors were logged.
error: the following test command failed with exit code 1:
/Users/kitanoyoru/Code/fun/zig/z/zig-cache/o/497544b27d5ac9c0b1837d7a0bed4b2b/test
Do you free what randomString
returns? It must be freed:
test "..." {
const allocator = ...
const random = try randomString(allocator, ...);
defer allocator.free(random);
// ...
}
Also, you don't need to duplicate the buffer, you can just return it:
pub fn randomString(allocator: std.mem.Allocator, size: u32, charset: []const u8) ![]u8 {
if (size == 0) {
return error.InvalidSize;
}
if (charset.len == 0) {
return error.InvalidCharset;
}
var prng = std.rand.DefaultPrng.init(blk: {
var seed: u64 = undefined;
try std.posix.getrandom(std.mem.asBytes(&seed));
break :blk seed;
});
var rand = prng.random();
const result = try allocator.alloc(u8, size);
for (result) |*ch| {
const idx = rand.int(u64) % charset.len;
ch.* = charset[idx];
}
return result;
}