fix memory leak on string arguments
This commit is contained in:
parent
b195577dee
commit
d7d4385242
2 changed files with 20 additions and 5 deletions
19
src/lang.zig
19
src/lang.zig
|
@ -479,6 +479,21 @@ pub const CommandList = struct {
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
for (self.list.items) |cmd_ptr| {
|
for (self.list.items) |cmd_ptr| {
|
||||||
self.list.allocator.destroy(cmd_ptr);
|
self.list.allocator.destroy(cmd_ptr);
|
||||||
|
inline for (@typeInfo(Command.Tag).Enum.fields) |field| {
|
||||||
|
if (cmd_ptr.tag == @field(Command.Tag, field.name)) {
|
||||||
|
const actual_tag =
|
||||||
|
@field(Command.Tag, field.name);
|
||||||
|
// if we find a match on the tag, we can get the type
|
||||||
|
const typ = Command.tagToType(actual_tag);
|
||||||
|
|
||||||
|
inline for (@typeInfo(typ).Struct.fields) |cmd_field| {
|
||||||
|
switch (cmd_field.field_type) {
|
||||||
|
[]u8, []const u8 => self.list.allocator.destroy(@field(typ, cmd_field.name)),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.list.deinit();
|
self.list.deinit();
|
||||||
}
|
}
|
||||||
|
@ -561,7 +576,7 @@ pub const Lang = struct {
|
||||||
f32 => try std.fmt.parseFloat(f32, arg),
|
f32 => try std.fmt.parseFloat(f32, arg),
|
||||||
u64 => try std.fmt.parseInt(u64, arg, 10),
|
u64 => try std.fmt.parseInt(u64, arg, 10),
|
||||||
usize => try std.fmt.parseInt(usize, arg, 10),
|
usize => try std.fmt.parseInt(usize, arg, 10),
|
||||||
[]const u8 => arg,
|
[]const u8 => @as([]const u8, try self.allocator.dupe(u8, arg)),
|
||||||
else => @compileError("parameter struct has unsupported type " ++ @typeName(cmd_field.field_type)),
|
else => @compileError("parameter struct has unsupported type " ++ @typeName(cmd_field.field_type)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -586,7 +601,7 @@ pub const Lang = struct {
|
||||||
usize => try std.fmt.parseInt(usize, arg, 10),
|
usize => try std.fmt.parseInt(usize, arg, 10),
|
||||||
i32 => try std.fmt.parseInt(i32, arg, 10),
|
i32 => try std.fmt.parseInt(i32, arg, 10),
|
||||||
f32 => try std.fmt.parseFloat(f32, arg),
|
f32 => try std.fmt.parseFloat(f32, arg),
|
||||||
[]const u8 => arg,
|
[]const u8 => @as([]const u8, try self.allocator.dupe(u8, arg)),
|
||||||
else => @compileError("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."),
|
else => @compileError("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: anytype) !void {
|
||||||
var stdout_file = std.io.getStdOut();
|
var stdout_file = std.io.getStdOut();
|
||||||
const stdout = &stdout_file.writer();
|
const stdout = &stdout_file.writer();
|
||||||
const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path"));
|
const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path"));
|
||||||
|
errdefer allocator.free(scri_path);
|
||||||
|
defer allocator.free(scri_path);
|
||||||
|
|
||||||
var file_read_opt: ?std.fs.File = std.fs.cwd().openFile(scri_path, .{}) catch |err| blk: {
|
var file_read_opt: ?std.fs.File = std.fs.cwd().openFile(scri_path, .{}) catch |err| blk: {
|
||||||
if (err == error.FileNotFound) break :blk null;
|
if (err == error.FileNotFound) break :blk null;
|
||||||
|
@ -54,11 +56,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: anytype) !void {
|
||||||
defer lang.deinit();
|
defer lang.deinit();
|
||||||
|
|
||||||
if (total_bytes > 0) {
|
if (total_bytes > 0) {
|
||||||
// this MUST BE long lived (a reference to it is kept inside
|
|
||||||
// existing_cmds, and then passed along to cmds),
|
|
||||||
// we can't defer them here
|
|
||||||
var scri_existing = try allocator.alloc(u8, total_bytes);
|
var scri_existing = try allocator.alloc(u8, total_bytes);
|
||||||
_ = try file_read_opt.?.read(scri_existing);
|
_ = try file_read_opt.?.read(scri_existing);
|
||||||
|
defer allocator.free(scri_existing);
|
||||||
|
|
||||||
// we can't defer this directly because we copy the
|
// we can't defer this directly because we copy the
|
||||||
// Command pointers to the cmds list. running deinit() directly
|
// Command pointers to the cmds list. running deinit() directly
|
||||||
|
|
Loading…
Reference in a new issue