authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-03-05 20:04:33+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-05 10:52:40-08:00
log9cd038d73a174706ec0a51ab9db0c04b095e019d
treed419221206f742c2c11b4680c5fa2ab006605833
parent291edafa1b3e6f56f88c3d1c542bdb25e99e45d1

std: fix memory leak in MultiArrayList


1 files changed, 69 insertions(+), 33 deletions(-)

lib/std/multi_array_list.zig+69-33
...@@ -8,6 +8,7 @@ const assert = std.debug.assert;...@@ -8,6 +8,7 @@ const assert = std.debug.assert;
8const meta = std.meta;8const meta = std.meta;
9const mem = std.mem;9const mem = std.mem;
10const Allocator = mem.Allocator;10const Allocator = mem.Allocator;
11const testing = std.testing;
1112
12pub fn MultiArrayList(comptime S: type) type {13pub fn MultiArrayList(comptime S: type) type {
13 return struct {14 return struct {
...@@ -247,6 +248,7 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -247,6 +248,7 @@ pub fn MultiArrayList(comptime S: type) type {
247 .exact,248 .exact,
248 );249 );
249 if (self.len == 0) {250 if (self.len == 0) {
251 gpa.free(self.allocatedBytes());
250 self.bytes = new_bytes.ptr;252 self.bytes = new_bytes.ptr;
251 self.capacity = new_capacity;253 self.capacity = new_capacity;
252 return;254 return;
...@@ -287,7 +289,6 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -287,7 +289,6 @@ pub fn MultiArrayList(comptime S: type) type {
287}289}
288290
289test "basic usage" {291test "basic usage" {
290 const testing = std.testing;
291 const ally = testing.allocator;292 const ally = testing.allocator;
292293
293 const Foo = struct {294 const Foo = struct {
...@@ -369,7 +370,7 @@ test "basic usage" {...@@ -369,7 +370,7 @@ test "basic usage" {
369// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes370// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes
370// function used the @reduce code path.371// function used the @reduce code path.
371test "regression test for @reduce bug" {372test "regression test for @reduce bug" {
372 const ally = std.testing.allocator;373 const ally = testing.allocator;
373 var list = MultiArrayList(struct {374 var list = MultiArrayList(struct {
374 tag: std.zig.Token.Tag,375 tag: std.zig.Token.Tag,
375 start: u32,376 start: u32,
...@@ -412,35 +413,70 @@ test "regression test for @reduce bug" {...@@ -412,35 +413,70 @@ test "regression test for @reduce bug" {
412 try list.append(ally, .{ .tag = .eof, .start = 123 });413 try list.append(ally, .{ .tag = .eof, .start = 123 });
413414
414 const tags = list.items(.tag);415 const tags = list.items(.tag);
415 std.testing.expectEqual(tags[1], .identifier);416 testing.expectEqual(tags[1], .identifier);
416 std.testing.expectEqual(tags[2], .equal);417 testing.expectEqual(tags[2], .equal);
417 std.testing.expectEqual(tags[3], .builtin);418 testing.expectEqual(tags[3], .builtin);
418 std.testing.expectEqual(tags[4], .l_paren);419 testing.expectEqual(tags[4], .l_paren);
419 std.testing.expectEqual(tags[5], .string_literal);420 testing.expectEqual(tags[5], .string_literal);
420 std.testing.expectEqual(tags[6], .r_paren);421 testing.expectEqual(tags[6], .r_paren);
421 std.testing.expectEqual(tags[7], .semicolon);422 testing.expectEqual(tags[7], .semicolon);
422 std.testing.expectEqual(tags[8], .keyword_pub);423 testing.expectEqual(tags[8], .keyword_pub);
423 std.testing.expectEqual(tags[9], .keyword_fn);424 testing.expectEqual(tags[9], .keyword_fn);
424 std.testing.expectEqual(tags[10], .identifier);425 testing.expectEqual(tags[10], .identifier);
425 std.testing.expectEqual(tags[11], .l_paren);426 testing.expectEqual(tags[11], .l_paren);
426 std.testing.expectEqual(tags[12], .r_paren);427 testing.expectEqual(tags[12], .r_paren);
427 std.testing.expectEqual(tags[13], .identifier);428 testing.expectEqual(tags[13], .identifier);
428 std.testing.expectEqual(tags[14], .bang);429 testing.expectEqual(tags[14], .bang);
429 std.testing.expectEqual(tags[15], .identifier);430 testing.expectEqual(tags[15], .identifier);
430 std.testing.expectEqual(tags[16], .l_brace);431 testing.expectEqual(tags[16], .l_brace);
431 std.testing.expectEqual(tags[17], .identifier);432 testing.expectEqual(tags[17], .identifier);
432 std.testing.expectEqual(tags[18], .period);433 testing.expectEqual(tags[18], .period);
433 std.testing.expectEqual(tags[19], .identifier);434 testing.expectEqual(tags[19], .identifier);
434 std.testing.expectEqual(tags[20], .period);435 testing.expectEqual(tags[20], .period);
435 std.testing.expectEqual(tags[21], .identifier);436 testing.expectEqual(tags[21], .identifier);
436 std.testing.expectEqual(tags[22], .l_paren);437 testing.expectEqual(tags[22], .l_paren);
437 std.testing.expectEqual(tags[23], .string_literal);438 testing.expectEqual(tags[23], .string_literal);
438 std.testing.expectEqual(tags[24], .comma);439 testing.expectEqual(tags[24], .comma);
439 std.testing.expectEqual(tags[25], .period);440 testing.expectEqual(tags[25], .period);
440 std.testing.expectEqual(tags[26], .l_brace);441 testing.expectEqual(tags[26], .l_brace);
441 std.testing.expectEqual(tags[27], .r_brace);442 testing.expectEqual(tags[27], .r_brace);
442 std.testing.expectEqual(tags[28], .r_paren);443 testing.expectEqual(tags[28], .r_paren);
443 std.testing.expectEqual(tags[29], .semicolon);444 testing.expectEqual(tags[29], .semicolon);
444 std.testing.expectEqual(tags[30], .r_brace);445 testing.expectEqual(tags[30], .r_brace);
445 std.testing.expectEqual(tags[31], .eof);446 testing.expectEqual(tags[31], .eof);
447}
448
449test "ensure capacity on empty list" {
450 const ally = testing.allocator;
451
452 const Foo = struct {
453 a: u32,
454 b: u8,
455 };
456
457 var list = MultiArrayList(Foo){};
458 defer list.deinit(ally);
459
460 try list.ensureCapacity(ally, 2);
461 list.appendAssumeCapacity(.{ .a = 1, .b = 2 });
462 list.appendAssumeCapacity(.{ .a = 3, .b = 4 });
463
464 testing.expectEqualSlices(u32, &[_]u32{ 1, 3 }, list.items(.a));
465 testing.expectEqualSlices(u8, &[_]u8{ 2, 4 }, list.items(.b));
466
467 list.len = 0;
468 list.appendAssumeCapacity(.{ .a = 5, .b = 6 });
469 list.appendAssumeCapacity(.{ .a = 7, .b = 8 });
470
471 testing.expectEqualSlices(u32, &[_]u32{ 5, 7 }, list.items(.a));
472 testing.expectEqualSlices(u8, &[_]u8{ 6, 8 }, list.items(.b));
473
474 list.len = 0;
475 try list.ensureCapacity(ally, 16);
476
477 list.appendAssumeCapacity(.{ .a = 9, .b = 10 });
478 list.appendAssumeCapacity(.{ .a = 11, .b = 12 });
479
480 testing.expectEqualSlices(u32, &[_]u32{ 9, 11 }, list.items(.a));
481 testing.expectEqualSlices(u8, &[_]u8{ 10, 12 }, list.items(.b));
446}482}