aboutsummaryrefslogtreecommitdiff
path: root/lib/std/multi_array_list.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2021-03-05 20:04:33 +0200
committerAndrew Kelley <andrew@ziglang.org>2021-03-05 10:52:40 -0800
commit9cd038d73a174706ec0a51ab9db0c04b095e019d (patch)
treed419221206f742c2c11b4680c5fa2ab006605833 /lib/std/multi_array_list.zig
parent291edafa1b3e6f56f88c3d1c542bdb25e99e45d1 (diff)
downloadzig-9cd038d73a174706ec0a51ab9db0c04b095e019d.tar.gz
zig-9cd038d73a174706ec0a51ab9db0c04b095e019d.zip
std: fix memory leak in MultiArrayList
Diffstat (limited to 'lib/std/multi_array_list.zig')
-rw-r--r--lib/std/multi_array_list.zig102
1 files changed, 69 insertions, 33 deletions
diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig
index 99a9fff7f0..37c4456d22 100644
--- a/lib/std/multi_array_list.zig
+++ b/lib/std/multi_array_list.zig
@@ -8,6 +8,7 @@ const assert = std.debug.assert;
const meta = std.meta;
const mem = std.mem;
const Allocator = mem.Allocator;
+const testing = std.testing;
pub fn MultiArrayList(comptime S: type) type {
return struct {
@@ -247,6 +248,7 @@ pub fn MultiArrayList(comptime S: type) type {
.exact,
);
if (self.len == 0) {
+ gpa.free(self.allocatedBytes());
self.bytes = new_bytes.ptr;
self.capacity = new_capacity;
return;
@@ -287,7 +289,6 @@ pub fn MultiArrayList(comptime S: type) type {
}
test "basic usage" {
- const testing = std.testing;
const ally = testing.allocator;
const Foo = struct {
@@ -369,7 +370,7 @@ test "basic usage" {
// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes
// function used the @reduce code path.
test "regression test for @reduce bug" {
- const ally = std.testing.allocator;
+ const ally = testing.allocator;
var list = MultiArrayList(struct {
tag: std.zig.Token.Tag,
start: u32,
@@ -412,35 +413,70 @@ test "regression test for @reduce bug" {
try list.append(ally, .{ .tag = .eof, .start = 123 });
const tags = list.items(.tag);
- std.testing.expectEqual(tags[1], .identifier);
- std.testing.expectEqual(tags[2], .equal);
- std.testing.expectEqual(tags[3], .builtin);
- std.testing.expectEqual(tags[4], .l_paren);
- std.testing.expectEqual(tags[5], .string_literal);
- std.testing.expectEqual(tags[6], .r_paren);
- std.testing.expectEqual(tags[7], .semicolon);
- std.testing.expectEqual(tags[8], .keyword_pub);
- std.testing.expectEqual(tags[9], .keyword_fn);
- std.testing.expectEqual(tags[10], .identifier);
- std.testing.expectEqual(tags[11], .l_paren);
- std.testing.expectEqual(tags[12], .r_paren);
- std.testing.expectEqual(tags[13], .identifier);
- std.testing.expectEqual(tags[14], .bang);
- std.testing.expectEqual(tags[15], .identifier);
- std.testing.expectEqual(tags[16], .l_brace);
- std.testing.expectEqual(tags[17], .identifier);
- std.testing.expectEqual(tags[18], .period);
- std.testing.expectEqual(tags[19], .identifier);
- std.testing.expectEqual(tags[20], .period);
- std.testing.expectEqual(tags[21], .identifier);
- std.testing.expectEqual(tags[22], .l_paren);
- std.testing.expectEqual(tags[23], .string_literal);
- std.testing.expectEqual(tags[24], .comma);
- std.testing.expectEqual(tags[25], .period);
- std.testing.expectEqual(tags[26], .l_brace);
- std.testing.expectEqual(tags[27], .r_brace);
- std.testing.expectEqual(tags[28], .r_paren);
- std.testing.expectEqual(tags[29], .semicolon);
- std.testing.expectEqual(tags[30], .r_brace);
- std.testing.expectEqual(tags[31], .eof);
+ testing.expectEqual(tags[1], .identifier);
+ testing.expectEqual(tags[2], .equal);
+ testing.expectEqual(tags[3], .builtin);
+ testing.expectEqual(tags[4], .l_paren);
+ testing.expectEqual(tags[5], .string_literal);
+ testing.expectEqual(tags[6], .r_paren);
+ testing.expectEqual(tags[7], .semicolon);
+ testing.expectEqual(tags[8], .keyword_pub);
+ testing.expectEqual(tags[9], .keyword_fn);
+ testing.expectEqual(tags[10], .identifier);
+ testing.expectEqual(tags[11], .l_paren);
+ testing.expectEqual(tags[12], .r_paren);
+ testing.expectEqual(tags[13], .identifier);
+ testing.expectEqual(tags[14], .bang);
+ testing.expectEqual(tags[15], .identifier);
+ testing.expectEqual(tags[16], .l_brace);
+ testing.expectEqual(tags[17], .identifier);
+ testing.expectEqual(tags[18], .period);
+ testing.expectEqual(tags[19], .identifier);
+ testing.expectEqual(tags[20], .period);
+ testing.expectEqual(tags[21], .identifier);
+ testing.expectEqual(tags[22], .l_paren);
+ testing.expectEqual(tags[23], .string_literal);
+ testing.expectEqual(tags[24], .comma);
+ testing.expectEqual(tags[25], .period);
+ testing.expectEqual(tags[26], .l_brace);
+ testing.expectEqual(tags[27], .r_brace);
+ testing.expectEqual(tags[28], .r_paren);
+ testing.expectEqual(tags[29], .semicolon);
+ testing.expectEqual(tags[30], .r_brace);
+ testing.expectEqual(tags[31], .eof);
+}
+
+test "ensure capacity on empty list" {
+ const ally = testing.allocator;
+
+ const Foo = struct {
+ a: u32,
+ b: u8,
+ };
+
+ var list = MultiArrayList(Foo){};
+ defer list.deinit(ally);
+
+ try list.ensureCapacity(ally, 2);
+ list.appendAssumeCapacity(.{ .a = 1, .b = 2 });
+ list.appendAssumeCapacity(.{ .a = 3, .b = 4 });
+
+ testing.expectEqualSlices(u32, &[_]u32{ 1, 3 }, list.items(.a));
+ testing.expectEqualSlices(u8, &[_]u8{ 2, 4 }, list.items(.b));
+
+ list.len = 0;
+ list.appendAssumeCapacity(.{ .a = 5, .b = 6 });
+ list.appendAssumeCapacity(.{ .a = 7, .b = 8 });
+
+ testing.expectEqualSlices(u32, &[_]u32{ 5, 7 }, list.items(.a));
+ testing.expectEqualSlices(u8, &[_]u8{ 6, 8 }, list.items(.b));
+
+ list.len = 0;
+ try list.ensureCapacity(ally, 16);
+
+ list.appendAssumeCapacity(.{ .a = 9, .b = 10 });
+ list.appendAssumeCapacity(.{ .a = 11, .b = 12 });
+
+ testing.expectEqualSlices(u32, &[_]u32{ 9, 11 }, list.items(.a));
+ testing.expectEqualSlices(u8, &[_]u8{ 10, 12 }, list.items(.b));
}