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;
88const meta = std.meta;
99const mem = std.mem;
1010const Allocator = mem.Allocator;
11const testing = std.testing;
1112
1213pub fn MultiArrayList(comptime S: type) type {
1314 return struct {
......@@ -247,6 +248,7 @@ pub fn MultiArrayList(comptime S: type) type {
247248 .exact,
248249 );
249250 if (self.len == 0) {
251 gpa.free(self.allocatedBytes());
250252 self.bytes = new_bytes.ptr;
251253 self.capacity = new_capacity;
252254 return;
......@@ -287,7 +289,6 @@ pub fn MultiArrayList(comptime S: type) type {
287289}
288290
289291test "basic usage" {
290 const testing = std.testing;
291292 const ally = testing.allocator;
292293
293294 const Foo = struct {
......@@ -369,7 +370,7 @@ test "basic usage" {
369370// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes
370371// function used the @reduce code path.
371372test "regression test for @reduce bug" {
372 const ally = std.testing.allocator;
373 const ally = testing.allocator;
373374 var list = MultiArrayList(struct {
374375 tag: std.zig.Token.Tag,
375376 start: u32,
......@@ -412,35 +413,70 @@ test "regression test for @reduce bug" {
412413 try list.append(ally, .{ .tag = .eof, .start = 123 });
413414
414415 const tags = list.items(.tag);
415 std.testing.expectEqual(tags[1], .identifier);
416 std.testing.expectEqual(tags[2], .equal);
417 std.testing.expectEqual(tags[3], .builtin);
418 std.testing.expectEqual(tags[4], .l_paren);
419 std.testing.expectEqual(tags[5], .string_literal);
420 std.testing.expectEqual(tags[6], .r_paren);
421 std.testing.expectEqual(tags[7], .semicolon);
422 std.testing.expectEqual(tags[8], .keyword_pub);
423 std.testing.expectEqual(tags[9], .keyword_fn);
424 std.testing.expectEqual(tags[10], .identifier);
425 std.testing.expectEqual(tags[11], .l_paren);
426 std.testing.expectEqual(tags[12], .r_paren);
427 std.testing.expectEqual(tags[13], .identifier);
428 std.testing.expectEqual(tags[14], .bang);
429 std.testing.expectEqual(tags[15], .identifier);
430 std.testing.expectEqual(tags[16], .l_brace);
431 std.testing.expectEqual(tags[17], .identifier);
432 std.testing.expectEqual(tags[18], .period);
433 std.testing.expectEqual(tags[19], .identifier);
434 std.testing.expectEqual(tags[20], .period);
435 std.testing.expectEqual(tags[21], .identifier);
436 std.testing.expectEqual(tags[22], .l_paren);
437 std.testing.expectEqual(tags[23], .string_literal);
438 std.testing.expectEqual(tags[24], .comma);
439 std.testing.expectEqual(tags[25], .period);
440 std.testing.expectEqual(tags[26], .l_brace);
441 std.testing.expectEqual(tags[27], .r_brace);
442 std.testing.expectEqual(tags[28], .r_paren);
443 std.testing.expectEqual(tags[29], .semicolon);
444 std.testing.expectEqual(tags[30], .r_brace);
445 std.testing.expectEqual(tags[31], .eof);
416 testing.expectEqual(tags[1], .identifier);
417 testing.expectEqual(tags[2], .equal);
418 testing.expectEqual(tags[3], .builtin);
419 testing.expectEqual(tags[4], .l_paren);
420 testing.expectEqual(tags[5], .string_literal);
421 testing.expectEqual(tags[6], .r_paren);
422 testing.expectEqual(tags[7], .semicolon);
423 testing.expectEqual(tags[8], .keyword_pub);
424 testing.expectEqual(tags[9], .keyword_fn);
425 testing.expectEqual(tags[10], .identifier);
426 testing.expectEqual(tags[11], .l_paren);
427 testing.expectEqual(tags[12], .r_paren);
428 testing.expectEqual(tags[13], .identifier);
429 testing.expectEqual(tags[14], .bang);
430 testing.expectEqual(tags[15], .identifier);
431 testing.expectEqual(tags[16], .l_brace);
432 testing.expectEqual(tags[17], .identifier);
433 testing.expectEqual(tags[18], .period);
434 testing.expectEqual(tags[19], .identifier);
435 testing.expectEqual(tags[20], .period);
436 testing.expectEqual(tags[21], .identifier);
437 testing.expectEqual(tags[22], .l_paren);
438 testing.expectEqual(tags[23], .string_literal);
439 testing.expectEqual(tags[24], .comma);
440 testing.expectEqual(tags[25], .period);
441 testing.expectEqual(tags[26], .l_brace);
442 testing.expectEqual(tags[27], .r_brace);
443 testing.expectEqual(tags[28], .r_paren);
444 testing.expectEqual(tags[29], .semicolon);
445 testing.expectEqual(tags[30], .r_brace);
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));
446482}