authorgravatar for clebs@users.noreply.github.comBorja Clemente <clebs@users.noreply.github.com> 2023-04-22 13:09:44+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-04-22 14:09:44+03:00
logbd801dc489ee4642050b1b6f11afb976c47425b8
tree0578ec3908dfd51c54dff010d2cfce7f644d34f7
parent3f259d35502ed5a8bdb6bbc22f9adb39d610b006
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std: GPA deinit return an enum instead of a bool


4 files changed, 28 insertions(+), 25 deletions(-)

lib/std/heap.zig+1
...@@ -16,6 +16,7 @@ pub const LogToWriterAllocator = @import("heap/log_to_writer_allocator.zig").Log...@@ -16,6 +16,7 @@ pub const LogToWriterAllocator = @import("heap/log_to_writer_allocator.zig").Log
16pub const logToWriterAllocator = @import("heap/log_to_writer_allocator.zig").logToWriterAllocator;16pub const logToWriterAllocator = @import("heap/log_to_writer_allocator.zig").logToWriterAllocator;
17pub const ArenaAllocator = @import("heap/arena_allocator.zig").ArenaAllocator;17pub const ArenaAllocator = @import("heap/arena_allocator.zig").ArenaAllocator;
18pub const GeneralPurposeAllocator = @import("heap/general_purpose_allocator.zig").GeneralPurposeAllocator;18pub const GeneralPurposeAllocator = @import("heap/general_purpose_allocator.zig").GeneralPurposeAllocator;
19pub const Check = @import("heap/general_purpose_allocator.zig").Check;
19pub const WasmAllocator = @import("heap/WasmAllocator.zig");20pub const WasmAllocator = @import("heap/WasmAllocator.zig");
20pub const WasmPageAllocator = @import("heap/WasmPageAllocator.zig");21pub const WasmPageAllocator = @import("heap/WasmPageAllocator.zig");
21pub const PageAllocator = @import("heap/PageAllocator.zig");22pub const PageAllocator = @import("heap/PageAllocator.zig");
lib/std/heap/general_purpose_allocator.zig+23-21
...@@ -155,6 +155,8 @@ pub const Config = struct {...@@ -155,6 +155,8 @@ pub const Config = struct {
155 verbose_log: bool = false,155 verbose_log: bool = false,
156};156};
157157
158pub const Check = enum { ok, leak };
159
158pub fn GeneralPurposeAllocator(comptime config: Config) type {160pub fn GeneralPurposeAllocator(comptime config: Config) type {
159 return struct {161 return struct {
160 backing_allocator: Allocator = std.heap.page_allocator,162 backing_allocator: Allocator = std.heap.page_allocator,
...@@ -431,7 +433,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -431,7 +433,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
431 } else struct {};433 } else struct {};
432434
433 /// Returns true if there were leaks; false otherwise.435 /// Returns true if there were leaks; false otherwise.
434 pub fn deinit(self: *Self) bool {436 pub fn deinit(self: *Self) Check {
435 const leaks = if (config.safety) self.detectLeaks() else false;437 const leaks = if (config.safety) self.detectLeaks() else false;
436 if (config.retain_metadata) {438 if (config.retain_metadata) {
437 self.freeRetainedMetadata();439 self.freeRetainedMetadata();
...@@ -441,7 +443,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -441,7 +443,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
441 self.small_allocations.deinit(self.backing_allocator);443 self.small_allocations.deinit(self.backing_allocator);
442 }444 }
443 self.* = undefined;445 self.* = undefined;
444 return leaks;446 return @intToEnum(Check, @boolToInt(leaks));
445 }447 }
446448
447 fn collectStackTrace(first_trace_addr: usize, addresses: *[stack_n]usize) void {449 fn collectStackTrace(first_trace_addr: usize, addresses: *[stack_n]usize) void {
...@@ -1024,7 +1026,7 @@ const test_config = Config{};...@@ -1024,7 +1026,7 @@ const test_config = Config{};
10241026
1025test "small allocations - free in same order" {1027test "small allocations - free in same order" {
1026 var gpa = GeneralPurposeAllocator(test_config){};1028 var gpa = GeneralPurposeAllocator(test_config){};
1027 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1029 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1028 const allocator = gpa.allocator();1030 const allocator = gpa.allocator();
10291031
1030 var list = std.ArrayList(*u64).init(std.testing.allocator);1032 var list = std.ArrayList(*u64).init(std.testing.allocator);
...@@ -1043,7 +1045,7 @@ test "small allocations - free in same order" {...@@ -1043,7 +1045,7 @@ test "small allocations - free in same order" {
10431045
1044test "small allocations - free in reverse order" {1046test "small allocations - free in reverse order" {
1045 var gpa = GeneralPurposeAllocator(test_config){};1047 var gpa = GeneralPurposeAllocator(test_config){};
1046 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1048 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1047 const allocator = gpa.allocator();1049 const allocator = gpa.allocator();
10481050
1049 var list = std.ArrayList(*u64).init(std.testing.allocator);1051 var list = std.ArrayList(*u64).init(std.testing.allocator);
...@@ -1062,7 +1064,7 @@ test "small allocations - free in reverse order" {...@@ -1062,7 +1064,7 @@ test "small allocations - free in reverse order" {
10621064
1063test "large allocations" {1065test "large allocations" {
1064 var gpa = GeneralPurposeAllocator(test_config){};1066 var gpa = GeneralPurposeAllocator(test_config){};
1065 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1067 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1066 const allocator = gpa.allocator();1068 const allocator = gpa.allocator();
10671069
1068 const ptr1 = try allocator.alloc(u64, 42768);1070 const ptr1 = try allocator.alloc(u64, 42768);
...@@ -1075,7 +1077,7 @@ test "large allocations" {...@@ -1075,7 +1077,7 @@ test "large allocations" {
10751077
1076test "very large allocation" {1078test "very large allocation" {
1077 var gpa = GeneralPurposeAllocator(test_config){};1079 var gpa = GeneralPurposeAllocator(test_config){};
1078 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1080 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1079 const allocator = gpa.allocator();1081 const allocator = gpa.allocator();
10801082
1081 try std.testing.expectError(error.OutOfMemory, allocator.alloc(u8, math.maxInt(usize)));1083 try std.testing.expectError(error.OutOfMemory, allocator.alloc(u8, math.maxInt(usize)));
...@@ -1083,7 +1085,7 @@ test "very large allocation" {...@@ -1083,7 +1085,7 @@ test "very large allocation" {
10831085
1084test "realloc" {1086test "realloc" {
1085 var gpa = GeneralPurposeAllocator(test_config){};1087 var gpa = GeneralPurposeAllocator(test_config){};
1086 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1088 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1087 const allocator = gpa.allocator();1089 const allocator = gpa.allocator();
10881090
1089 var slice = try allocator.alignedAlloc(u8, @alignOf(u32), 1);1091 var slice = try allocator.alignedAlloc(u8, @alignOf(u32), 1);
...@@ -1105,7 +1107,7 @@ test "realloc" {...@@ -1105,7 +1107,7 @@ test "realloc" {
11051107
1106test "shrink" {1108test "shrink" {
1107 var gpa = GeneralPurposeAllocator(test_config){};1109 var gpa = GeneralPurposeAllocator(test_config){};
1108 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1110 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1109 const allocator = gpa.allocator();1111 const allocator = gpa.allocator();
11101112
1111 var slice = try allocator.alloc(u8, 20);1113 var slice = try allocator.alloc(u8, 20);
...@@ -1130,7 +1132,7 @@ test "shrink" {...@@ -1130,7 +1132,7 @@ test "shrink" {
11301132
1131test "large object - grow" {1133test "large object - grow" {
1132 var gpa = GeneralPurposeAllocator(test_config){};1134 var gpa = GeneralPurposeAllocator(test_config){};
1133 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1135 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1134 const allocator = gpa.allocator();1136 const allocator = gpa.allocator();
11351137
1136 var slice1 = try allocator.alloc(u8, page_size * 2 - 20);1138 var slice1 = try allocator.alloc(u8, page_size * 2 - 20);
...@@ -1148,7 +1150,7 @@ test "large object - grow" {...@@ -1148,7 +1150,7 @@ test "large object - grow" {
11481150
1149test "realloc small object to large object" {1151test "realloc small object to large object" {
1150 var gpa = GeneralPurposeAllocator(test_config){};1152 var gpa = GeneralPurposeAllocator(test_config){};
1151 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1153 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1152 const allocator = gpa.allocator();1154 const allocator = gpa.allocator();
11531155
1154 var slice = try allocator.alloc(u8, 70);1156 var slice = try allocator.alloc(u8, 70);
...@@ -1165,7 +1167,7 @@ test "realloc small object to large object" {...@@ -1165,7 +1167,7 @@ test "realloc small object to large object" {
11651167
1166test "shrink large object to large object" {1168test "shrink large object to large object" {
1167 var gpa = GeneralPurposeAllocator(test_config){};1169 var gpa = GeneralPurposeAllocator(test_config){};
1168 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1170 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1169 const allocator = gpa.allocator();1171 const allocator = gpa.allocator();
11701172
1171 var slice = try allocator.alloc(u8, page_size * 2 + 50);1173 var slice = try allocator.alloc(u8, page_size * 2 + 50);
...@@ -1190,7 +1192,7 @@ test "shrink large object to large object" {...@@ -1190,7 +1192,7 @@ test "shrink large object to large object" {
11901192
1191test "shrink large object to large object with larger alignment" {1193test "shrink large object to large object with larger alignment" {
1192 var gpa = GeneralPurposeAllocator(test_config){};1194 var gpa = GeneralPurposeAllocator(test_config){};
1193 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1195 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1194 const allocator = gpa.allocator();1196 const allocator = gpa.allocator();
11951197
1196 var debug_buffer: [1000]u8 = undefined;1198 var debug_buffer: [1000]u8 = undefined;
...@@ -1226,7 +1228,7 @@ test "shrink large object to large object with larger alignment" {...@@ -1226,7 +1228,7 @@ test "shrink large object to large object with larger alignment" {
12261228
1227test "realloc large object to small object" {1229test "realloc large object to small object" {
1228 var gpa = GeneralPurposeAllocator(test_config){};1230 var gpa = GeneralPurposeAllocator(test_config){};
1229 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1231 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1230 const allocator = gpa.allocator();1232 const allocator = gpa.allocator();
12311233
1232 var slice = try allocator.alloc(u8, page_size * 2 + 50);1234 var slice = try allocator.alloc(u8, page_size * 2 + 50);
...@@ -1244,7 +1246,7 @@ test "overrideable mutexes" {...@@ -1244,7 +1246,7 @@ test "overrideable mutexes" {
1244 .backing_allocator = std.testing.allocator,1246 .backing_allocator = std.testing.allocator,
1245 .mutex = std.Thread.Mutex{},1247 .mutex = std.Thread.Mutex{},
1246 };1248 };
1247 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1249 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1248 const allocator = gpa.allocator();1250 const allocator = gpa.allocator();
12491251
1250 const ptr = try allocator.create(i32);1252 const ptr = try allocator.create(i32);
...@@ -1253,7 +1255,7 @@ test "overrideable mutexes" {...@@ -1253,7 +1255,7 @@ test "overrideable mutexes" {
12531255
1254test "non-page-allocator backing allocator" {1256test "non-page-allocator backing allocator" {
1255 var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = std.testing.allocator };1257 var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = std.testing.allocator };
1256 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1258 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1257 const allocator = gpa.allocator();1259 const allocator = gpa.allocator();
12581260
1259 const ptr = try allocator.create(i32);1261 const ptr = try allocator.create(i32);
...@@ -1262,7 +1264,7 @@ test "non-page-allocator backing allocator" {...@@ -1262,7 +1264,7 @@ test "non-page-allocator backing allocator" {
12621264
1263test "realloc large object to larger alignment" {1265test "realloc large object to larger alignment" {
1264 var gpa = GeneralPurposeAllocator(test_config){};1266 var gpa = GeneralPurposeAllocator(test_config){};
1265 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1267 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1266 const allocator = gpa.allocator();1268 const allocator = gpa.allocator();
12671269
1268 var debug_buffer: [1000]u8 = undefined;1270 var debug_buffer: [1000]u8 = undefined;
...@@ -1304,7 +1306,7 @@ test "realloc large object to larger alignment" {...@@ -1304,7 +1306,7 @@ test "realloc large object to larger alignment" {
1304test "large object shrinks to small but allocation fails during shrink" {1306test "large object shrinks to small but allocation fails during shrink" {
1305 var failing_allocator = std.testing.FailingAllocator.init(std.heap.page_allocator, 3);1307 var failing_allocator = std.testing.FailingAllocator.init(std.heap.page_allocator, 3);
1306 var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = failing_allocator.allocator() };1308 var gpa = GeneralPurposeAllocator(.{}){ .backing_allocator = failing_allocator.allocator() };
1307 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1309 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1308 const allocator = gpa.allocator();1310 const allocator = gpa.allocator();
13091311
1310 var slice = try allocator.alloc(u8, page_size * 2 + 50);1312 var slice = try allocator.alloc(u8, page_size * 2 + 50);
...@@ -1322,7 +1324,7 @@ test "large object shrinks to small but allocation fails during shrink" {...@@ -1322,7 +1324,7 @@ test "large object shrinks to small but allocation fails during shrink" {
13221324
1323test "objects of size 1024 and 2048" {1325test "objects of size 1024 and 2048" {
1324 var gpa = GeneralPurposeAllocator(test_config){};1326 var gpa = GeneralPurposeAllocator(test_config){};
1325 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1327 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1326 const allocator = gpa.allocator();1328 const allocator = gpa.allocator();
13271329
1328 const slice = try allocator.alloc(u8, 1025);1330 const slice = try allocator.alloc(u8, 1025);
...@@ -1334,7 +1336,7 @@ test "objects of size 1024 and 2048" {...@@ -1334,7 +1336,7 @@ test "objects of size 1024 and 2048" {
13341336
1335test "setting a memory cap" {1337test "setting a memory cap" {
1336 var gpa = GeneralPurposeAllocator(.{ .enable_memory_limit = true }){};1338 var gpa = GeneralPurposeAllocator(.{ .enable_memory_limit = true }){};
1337 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1339 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1338 const allocator = gpa.allocator();1340 const allocator = gpa.allocator();
13391341
1340 gpa.setRequestedMemoryLimit(1010);1342 gpa.setRequestedMemoryLimit(1010);
...@@ -1361,11 +1363,11 @@ test "setting a memory cap" {...@@ -1361,11 +1363,11 @@ test "setting a memory cap" {
1361test "double frees" {1363test "double frees" {
1362 // use a GPA to back a GPA to check for leaks of the latter's metadata1364 // use a GPA to back a GPA to check for leaks of the latter's metadata
1363 var backing_gpa = GeneralPurposeAllocator(.{ .safety = true }){};1365 var backing_gpa = GeneralPurposeAllocator(.{ .safety = true }){};
1364 defer std.testing.expect(!backing_gpa.deinit()) catch @panic("leak");1366 defer std.testing.expect(backing_gpa.deinit() == .ok) catch @panic("leak");
13651367
1366 const GPA = GeneralPurposeAllocator(.{ .safety = true, .never_unmap = true, .retain_metadata = true });1368 const GPA = GeneralPurposeAllocator(.{ .safety = true, .never_unmap = true, .retain_metadata = true });
1367 var gpa = GPA{ .backing_allocator = backing_gpa.allocator() };1369 var gpa = GPA{ .backing_allocator = backing_gpa.allocator() };
1368 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");1370 defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
1369 const allocator = gpa.allocator();1371 const allocator = gpa.allocator();
13701372
1371 // detect a small allocation double free, even though bucket is emptied1373 // detect a small allocation double free, even though bucket is emptied
lib/test_runner.zig+3-3
...@@ -56,7 +56,7 @@ fn mainServer() !void {...@@ -56,7 +56,7 @@ fn mainServer() !void {
56 },56 },
57 .query_test_metadata => {57 .query_test_metadata => {
58 std.testing.allocator_instance = .{};58 std.testing.allocator_instance = .{};
59 defer if (std.testing.allocator_instance.deinit()) {59 defer if (std.testing.allocator_instance.deinit() == .leak) {
60 @panic("internal test runner memory leak");60 @panic("internal test runner memory leak");
61 };61 };
6262
...@@ -108,7 +108,7 @@ fn mainServer() !void {...@@ -108,7 +108,7 @@ fn mainServer() !void {
108 }108 }
109 },109 },
110 };110 };
111 leak = std.testing.allocator_instance.deinit();111 leak = std.testing.allocator_instance.deinit() == .leak;
112 try server.serveTestResults(.{112 try server.serveTestResults(.{
113 .index = index,113 .index = index,
114 .flags = .{114 .flags = .{
...@@ -148,7 +148,7 @@ fn mainTerminal() void {...@@ -148,7 +148,7 @@ fn mainTerminal() void {
148 for (test_fn_list, 0..) |test_fn, i| {148 for (test_fn_list, 0..) |test_fn, i| {
149 std.testing.allocator_instance = .{};149 std.testing.allocator_instance = .{};
150 defer {150 defer {
151 if (std.testing.allocator_instance.deinit()) {151 if (std.testing.allocator_instance.deinit() == .leak) {
152 leaks += 1;152 leaks += 1;
153 }153 }
154 }154 }
test/standalone/windows_spawn/main.zig+1-1
...@@ -4,7 +4,7 @@ const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral;...@@ -4,7 +4,7 @@ const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral;
44
5pub fn main() anyerror!void {5pub fn main() anyerror!void {
6 var gpa = std.heap.GeneralPurposeAllocator(.{}){};6 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
7 defer if (gpa.deinit()) @panic("found memory leaks");7 defer if (gpa.deinit() == .leak) @panic("found memory leaks");
8 const allocator = gpa.allocator();8 const allocator = gpa.allocator();
99
10 var it = try std.process.argsWithAllocator(allocator);10 var it = try std.process.argsWithAllocator(allocator);