I’m working with a tagged union defined like this:
pub const Lex = union(enum) {
EOF,
// ... other variants ...
SLASH,
STRING: []const u8,
NUMBER: []const u8,
// ... other variants ...
};
I have a tokenization function that processes numbers like this:
'0'...'9' => {
var num_builder = std.ArrayList(u8).init(allocator);
defer num_builder.deinit();
while (i < input.len and (std.ascii.isDigit(input[i]) or input[i] == '.')) : (i += 1) {
try num_builder.append(input[i]);
}
const num_str = try num_builder.toOwnedSlice();
try list.append(.{ .NUMBER = num_str });
continue;
},
My concern is about memory management. I use ArrayList to build the number string and then call toOwnedSlice() to get an owned slice, which I store in my Lex.NUMBER variant. However, I’m unsure how to properly clean up the memory allocated by toOwnedSlice(). The defer num_builder.deinit() only cleans up the ArrayList’s internal buffer, but not the slice returned by toOwnedSlice(), right?
When I run my application, I get a memory leak reported:
/usr/lib/zig/std/array_list.zig:483:41: 0x1061580 in addOne (main)
try self.ensureTotalCapacity(newlen);
^
/usr/lib/zig/std/array_list.zig:262:49: 0x104f35e in append (main)
const new_item_ptr = try self.addOne();
^
codecrafters/codecrafters-interpreter-zig/src/token.zig:187:43: 0x104e7c3 in tokenize (main)
try num_builder.append(input[i]);
^
codecrafters-interpreter-zig/src/main.zig:51:42: 0x10579b3 in main (main)
const tokens = try token.tokenize(allocator, file_contents, &is_err);
How should I modify my code to prevent this leak?
Should I be managing the Lex.NUMBER slice’s memory differently?