Added build option to enable the leak counting allocator.

Log the allocation count to the client at the end of the main loop.
Fixed two memory leaks in analysis.zig
This commit is contained in:
Alexandros Naskos 2020-05-07 12:50:25 +03:00
parent 5bd790f416
commit 0283222e3a
3 changed files with 29 additions and 6 deletions

View File

@ -16,6 +16,12 @@ pub fn build(b: *std.build.Builder) void {
exe.addPackagePath("data", "src/data/0.6.0.zig"); exe.addPackagePath("data", "src/data/0.6.0.zig");
exe.addBuildOption(
bool,
"leak_detection",
b.option(bool, "leak_detection", "Use testing.LeakCountAllocator to track leaks.") orelse false,
);
exe.setTarget(target); exe.setTarget(target);
exe.setBuildMode(mode); exe.setBuildMode(mode);
exe.install(); exe.install();

View File

@ -30,12 +30,13 @@ pub fn getDocComments(allocator: *std.mem.Allocator, tree: *std.zig.ast.Tree, no
if (func.doc_comments) |doc_comments| { if (func.doc_comments) |doc_comments| {
var doc_it = doc_comments.lines.iterator(0); var doc_it = doc_comments.lines.iterator(0);
var lines = std.ArrayList([]const u8).init(allocator); var lines = std.ArrayList([]const u8).init(allocator);
defer lines.deinit();
while (doc_it.next()) |doc_comment| { while (doc_it.next()) |doc_comment| {
_ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..])); _ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..]));
} }
return try std.mem.join(allocator, "\n", lines.toOwnedSlice()); return try std.mem.join(allocator, "\n", lines.items);
} else { } else {
return null; return null;
} }
@ -45,12 +46,13 @@ pub fn getDocComments(allocator: *std.mem.Allocator, tree: *std.zig.ast.Tree, no
if (var_decl.doc_comments) |doc_comments| { if (var_decl.doc_comments) |doc_comments| {
var doc_it = doc_comments.lines.iterator(0); var doc_it = doc_comments.lines.iterator(0);
var lines = std.ArrayList([]const u8).init(allocator); var lines = std.ArrayList([]const u8).init(allocator);
defer lines.deinit();
while (doc_it.next()) |doc_comment| { while (doc_it.next()) |doc_comment| {
_ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..])); _ = try lines.append(std.fmt.trim(tree.tokenSlice(doc_comment.*)[3..]));
} }
return try std.mem.join(allocator, "\n", lines.toOwnedSlice()); return try std.mem.join(allocator, "\n", lines.items);
} else { } else {
return null; return null;
} }

View File

@ -164,7 +164,8 @@ pub fn completeGlobal(id: i64, document: types.TextDocument) !void {
var completions = std.ArrayList(types.CompletionItem).init(allocator); var completions = std.ArrayList(types.CompletionItem).init(allocator);
// try log("{}", .{&tree.root_node.decls}); // @TODO
try log("{}", .{&tree.root_node.decls});
var decls = tree.root_node.decls.iterator(0); var decls = tree.root_node.decls.iterator(0);
while (decls.next()) |decl_ptr| { while (decls.next()) |decl_ptr| {
@ -356,9 +357,14 @@ pub fn processJsonRpc(json: []const u8) !void {
} else { } else {
try log("Method without return value not implemented: {}", .{method}); try log("Method without return value not implemented: {}", .{method});
} }
} }
const use_leak_count_alloc = @import("build_options").leak_detection;
var leak_alloc_global: std.testing.LeakCountAllocator = undefined;
// We can now use if(leak_count_alloc) |alloc| { ... } as a comptime check.
const leak_count_alloc: ?*std.testing.LeakCountAllocator = if (use_leak_count_alloc) &leak_alloc_global else null;
pub fn main() anyerror!void { pub fn main() anyerror!void {
// Init memory // Init memory
@ -367,6 +373,12 @@ pub fn main() anyerror!void {
defer arena.deinit(); defer arena.deinit();
allocator = &arena.allocator; allocator = &arena.allocator;
if (use_leak_count_alloc) {
// Initialize the leak counting allocator.
leak_alloc_global = std.testing.LeakCountAllocator.init(allocator);
allocator = &leak_alloc_global.allocator;
}
// Init buffer for stdin read // Init buffer for stdin read
var buffer = std.ArrayList(u8).init(allocator); var buffer = std.ArrayList(u8).init(allocator);
@ -391,7 +403,7 @@ pub fn main() anyerror!void {
// var bytes = stdin.read(buffer.items[0..6]) catch return; // var bytes = stdin.read(buffer.items[0..6]) catch return;
if (offset >= 16 and std.mem.eql(u8, "Content-Length: ", buffer.items[0..16])) { if (offset >= 16 and std.mem.startsWith(u8, buffer.items, "Content-Length: ")) {
index = 16; index = 16;
while (index <= offset + 10) : (index += 1) { while (index <= offset + 10) : (index += 1) {
@ -430,7 +442,7 @@ pub fn main() anyerror!void {
} }
} else if (offset >= 16) { } else if (offset >= 16) {
try log("Offset is greater than 16!", .{}); try log("OffseOt is greater than 16!", .{});
return; return;
} }
@ -460,5 +472,8 @@ pub fn main() anyerror!void {
offset += bytes_read; offset += bytes_read;
if (leak_count_alloc) |leaks| {
try log("Allocations alive after message: {}", .{leaks.count});
}
} }
} }