#Segmentation error when freeing memory

1 messages · Page 1 of 1 (latest)

rain merlin
#

Hallo everyone,

I'm kind of new to zig and I'm getting a segmentation error when freeing memory that I think is not used. Can someone explain to me why this happens? Am I pushing references on the arrayList?

See the code in the next post, the line defer allocator.free(file_contents); causes the application to crash. Without this line it runs fine but the test complains about a memory leak.

#
fn readFileIntoArrayList(allocator: std.mem.Allocator, array_list: *std.ArrayList([]const u8), filename: []const u8) !void {
    var file = try std.fs.cwd().openFile(filename, .{});
    defer file.close();
 
    var file_contents = try file.reader().readAllAlloc(allocator, 1024 * 1024);
    defer allocator.free(file_contents); // without this line the code runs fine but comlpains about a memory leak
 
    var split = std.mem.split(u8, file_contents, "\n");
    while (split.next()) |line| {
        try array_list.append(line);
    }
}
 
test "day 1 - part 1" {
    const allocator = std.testing.allocator;
    var file_contents = std.ArrayList([]const u8).init(allocator);
    defer file_contents.deinit();
 
    try readFileIntoArrayList(allocator, &file_contents, "./aoc-input/1_1.txt");
 
    var index: usize = 0;
 
    var max: u32 = 0;
    var currentSum: u32 = 0;
 
    while (index < file_contents.items.len) {
        var line = file_contents.items[index];
        index = index + 1;
 
        if (line.len != 0) {
            var value = try std.fmt.parseInt(u32, line, 10);
            currentSum = currentSum + value;
        } else {
            if (max < currentSum) {
                max = currentSum;
            }
            currentSum = 0;
        }
    }
 
    std.debug.print("{d}\n", .{max});
}
#

Segmentation fault at address 0x7f817d4bb000
/snap/zig/8241/lib/std/fmt.zig:1737:12: 0x220a7b in parseInt__anon_4064 (aoc-zig)
if (buf[0] == '+') return parseWithSign(T, buf[1..], base, .pos);
^
/root/dev/aoc-zig/src/main.zig:20:45: 0x22088c in main (aoc-zig)
var value = try std.fmt.parseInt(u32, line, 10);
^
/snap/zig/8241/lib/std/start.zig:574:37: 0x21ee5e in posixCallMainAndExit (aoc-zig)
const result = root.main() catch |err| {
^
/snap/zig/8241/lib/std/start.zig:243:5: 0x21e941 in _start (aoc-zig)
asm volatile (switch (native_arch) {
^
???:?:?: 0x0 in ??? (???)

green path
#

Split doesn't allocate but uses the underlying memory. That's why freeing the file contents results in a seg fault.

What you probably want is

- try array_list.append(line);
+ try array_list.append(try allocator.dupe(u8, line));

And finally you'll have to free that memory, each line in the array list which is now its own allocation, at some point as well

rain merlin
#

Is there a way to free all allocated memory in one go?

green path
#

A more idiomatic way might be to get rid of the ArrayList and work with the SplitIterator directly while having some helper function that just reads the entire file contents

green path
# rain merlin Is there a way to free all allocated memory in one go?

My last suggestion would do that, you just have the file content allocation and once you have done your sum calculation you'd free it, well you'd have the defer before the loop but still.

Alternatively you could also use an ArenaAllocator and wrap your current allocator with that and not worry about the individual allocations but just deinit / reset the arena afterwards.