Skip to content

Commit 74b14ed

Browse files
jacobly0andrewrk
authored andcommitted
link: fix memory leaks
* Fix linker memory leaks found while running `zig build test-cases`. * Add missing target to test manifest.
1 parent 70ac9fc commit 74b14ed

File tree

5 files changed

+35
-14
lines changed

5 files changed

+35
-14
lines changed

src/link.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ pub const Options = struct {
223223

224224
pub fn move(self: *Options) Options {
225225
const copied_state = self.*;
226+
self.frameworks = .{};
226227
self.system_libs = .{};
228+
self.force_undefined_symbols = .{};
227229
return copied_state;
228230
}
229231
};
@@ -624,7 +626,9 @@ pub const File = struct {
624626
base.releaseLock();
625627
if (base.file) |f| f.close();
626628
if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);
629+
base.options.frameworks.deinit(base.allocator);
627630
base.options.system_libs.deinit(base.allocator);
631+
base.options.force_undefined_symbols.deinit(base.allocator);
628632
switch (base.tag) {
629633
.coff => {
630634
if (build_options.only_c) unreachable;

src/link/Coff.zig

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ pub fn deinit(self: *Coff) void {
289289

290290
self.unresolved.deinit(gpa);
291291
self.locals_free_list.deinit(gpa);
292+
self.globals_free_list.deinit(gpa);
292293
self.strtab.deinit(gpa);
293294
self.got_entries.deinit(gpa);
294295
self.got_entries_free_list.deinit(gpa);
@@ -1150,8 +1151,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
11501151
}
11511152

11521153
fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void {
1153-
_ = self.relocs.remove(atom);
1154-
_ = self.base_relocs.remove(atom);
1154+
var removed_relocs = self.relocs.fetchRemove(atom);
1155+
if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
1156+
var removed_base_relocs = self.base_relocs.fetchRemove(atom);
1157+
if (removed_base_relocs) |*base_relocs| base_relocs.value.deinit(self.base.allocator);
11551158
}
11561159

11571160
fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void {
@@ -1489,9 +1492,8 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {
14891492
gop.value_ptr.* = sym_loc;
14901493

14911494
const gpa = self.base.allocator;
1492-
const sym_name = try gpa.dupe(u8, name);
14931495
const sym = self.getSymbolPtr(sym_loc);
1494-
try self.setSymbolName(sym, sym_name);
1496+
try self.setSymbolName(sym, name);
14951497
sym.storage_class = .EXTERNAL;
14961498

14971499
try self.unresolved.putNoClobber(gpa, global_index, true);

src/link/MachO.zig

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2576,10 +2576,14 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
25762576
}
25772577

25782578
fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void {
2579-
_ = self.relocs.remove(atom);
2580-
_ = self.rebases.remove(atom);
2581-
_ = self.bindings.remove(atom);
2582-
_ = self.lazy_bindings.remove(atom);
2579+
var removed_relocs = self.relocs.fetchRemove(atom);
2580+
if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
2581+
var removed_rebases = self.rebases.fetchRemove(atom);
2582+
if (removed_rebases) |*rebases| rebases.value.deinit(self.base.allocator);
2583+
var removed_bindings = self.bindings.fetchRemove(atom);
2584+
if (removed_bindings) |*bindings| bindings.value.deinit(self.base.allocator);
2585+
var removed_lazy_bindings = self.lazy_bindings.fetchRemove(atom);
2586+
if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(self.base.allocator);
25832587
}
25842588

25852589
fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {

src/link/Plan9.zig

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,10 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void {
201201
const decl = mod.declPtr(decl_index);
202202
const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope());
203203
if (fn_map_res.found_existing) {
204-
try fn_map_res.value_ptr.functions.put(gpa, decl_index, out);
204+
if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| {
205+
gpa.free(old_entry.value.code);
206+
gpa.free(old_entry.value.lineinfo);
207+
}
205208
} else {
206209
const file = decl.getFileScope();
207210
const arena = self.path_arena.allocator();
@@ -408,9 +411,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
408411
return;
409412
},
410413
};
411-
var duped_code = try self.base.allocator.dupe(u8, code);
412-
errdefer self.base.allocator.free(duped_code);
413-
try self.data_decl_table.put(self.base.allocator, decl_index, duped_code);
414+
try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1);
415+
const duped_code = try self.base.allocator.dupe(u8, code);
416+
if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {
417+
self.base.allocator.free(old_entry.value);
418+
}
414419
return self.updateFinish(decl);
415420
}
416421
/// called at the end of update{Decl,Func}
@@ -743,14 +748,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
743748
if (is_fn) {
744749
var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?;
745750
var submap = symidx_and_submap.functions;
746-
_ = submap.swapRemove(decl_index);
751+
if (submap.fetchSwapRemove(decl_index)) |removed_entry| {
752+
self.base.allocator.free(removed_entry.value.code);
753+
self.base.allocator.free(removed_entry.value.lineinfo);
754+
}
747755
if (submap.count() == 0) {
748756
self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol;
749757
self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {};
750758
submap.deinit(self.base.allocator);
751759
}
752760
} else {
753-
_ = self.data_decl_table.swapRemove(decl_index);
761+
if (self.data_decl_table.fetchSwapRemove(decl_index)) |removed_entry| {
762+
self.base.allocator.free(removed_entry.value);
763+
}
754764
}
755765
if (decl.link.plan9.got_index) |i| {
756766
// TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length

test/cases/plan9/hello_world_with_updates.1.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub fn main() void {
55
}
66

77
// run
8+
// target=x86_64-plan9
89
//
910
// Hello World
1011
//

0 commit comments

Comments
 (0)