#ArrayList.append leaking memory

1 messages · Page 1 of 1 (latest)

half spire
#

Hello, i'm building a small compiler and i came to the part when i need to use an arraylist. But the thing is that i keep leaking memory and i don't understand why.

error(gpa): memory address leaked: 
lib/std/array_list.zig:474:67: in ensureTotalCapacityPrecise (oneth)
                const new_memory = try self.allocator.alignedAlloc(T, alignment, new_capacity);

lib/std/array_list.zig:450:51: in ensureTotalCapacity (oneth)
            return self.ensureTotalCapacityPrecise(better_capacity);

lib/std/array_list.zig:500:41: in addOne (oneth)
            try self.ensureTotalCapacity(newlen);

lib/std/array_list.zig:261:49: in append (oneth)
            const new_item_ptr = try self.addOne();

oneth/src/codegen.zig:54:22: in genInt (oneth)
    try c.code.append(opcode);

oneth/src/codegen.zig:41:44: 0x10f0082 in gen (oneth)
            .number_literal => try c.genInt(),

The code

pub fn init(gpa: std.mem.Allocator, source: [:0]const u8, tokens: TokenList.Slice) CodeGen {
    return .{
        .string_map = .init(gpa),
        .token_tags = tokens.items(.tag),
        .token_locs = tokens.items(.loc),
        .source = source,
        .code = .init(gpa),
        .gpa = gpa,
    };
}

pub fn gen(c: *CodeGen) ![]const u8 {
    while (c.tp < c.token_tags.len) : (c.tp += 1) {
        switch (c.token_tags[c.tp]) {
            .number_literal => try c.genInt(),
            else => {},
        }
    }
    
    return c.code.toOwnedSlice();
}

fn genInt(c: *CodeGen) !void {
    const start = c.token_locs[c.tp].start;
    const end = c.token_locs[c.tp].stop;

    const opcode: u8 = @intFromEnum(OpCode.int);
    try c.code.append(opcode);
    std.log.info("int: `{s}`\n", .{ c.source[start..end] });
    const int = try std.fmt.parseInt(usize, c.source[start..end], 10);
    const bytes = std.mem.toBytes(int);
    try c.code.appendSlice(&bytes);
}

I'm using the general purpose allocator in an arraylist of u8.
If you have an idea, i might just have skip something

tight gust
#

and youre calling c.code.deinit() at some point?

half spire
#

Oh no .......;

#

bruh

#

But even after that it still leaks

#

Caller

var code: CodeGen = .init(allocator, input, tokens);
defer code.deinit();

const bytcode = try code.gen();

Callee deinit

pub fn deinit(c: *CodeGen) void {
    c.string_map.deinit();
    c.code.deinit();
}
ashen heart
#

what's the definition of CodeGen and what is the current stack trace for the leak

half spire
#

Same as above

error(gpa): memory address 0x7fbce3180000 leaked: 
/home/bastien/.cache/zig/p/N-V-__8AANS1ihIOtIbwStI19vHd9274HDAeXLQjJFgZzdsY/lib/std/array_list.zig:474:67: 0x10f5222 in ensureTotalCapacityPrecise (oneth)
                const new_memory = try self.allocator.alignedAlloc(T, alignment, new_capacity);
                                                                  ^
/home/bastien/.cache/zig/p/N-V-__8AANS1ihIOtIbwStI19vHd9274HDAeXLQjJFgZzdsY/lib/std/array_list.zig:450:51: 0x10f5440 in ensureTotalCapacity (oneth)
            return self.ensureTotalCapacityPrecise(better_capacity);
                                                  ^
/home/bastien/.cache/zig/p/N-V-__8AANS1ihIOtIbwStI19vHd9274HDAeXLQjJFgZzdsY/lib/std/array_list.zig:500:41: 0x10f64ef in addOne (oneth)
            try self.ensureTotalCapacity(newlen);
                                        ^
/home/bastien/.cache/zig/p/N-V-__8AANS1ihIOtIbwStI19vHd9274HDAeXLQjJFgZzdsY/lib/std/array_list.zig:261:49: 0x10efdee in append (oneth)
            const new_item_ptr = try self.addOne();
                                                ^
/home/bastien/Projets/oneth/src/codegen.zig:55:22: 0x10efab2 in genInt (oneth)
    try c.code.append(opcode);
                     ^
/home/bastien/Projets/oneth/src/codegen.zig:42:44: 0x10f0082 in gen (oneth)
            .number_literal => try c.genInt(),
#

The only missing part of CodeGen

const std = @import("std");
const lexer = @import("lexer.zig");
const OpCode = @import("bytecode.zig").OpCode;

const Token = lexer.Token;
const TokenList = lexer.TokenList;

/// Universal index used for labels, consts, vars and functions
idx: u16 = 0,
/// Convert an identifier to its index
string_map: std.StringHashMap(u16),
/// Token pointer
tp: u32 = 0,
token_tags: []Token.Tag,
token_locs: []Token.Loc,
source: [:0]const u8,
/// Bytecode
code: std.ArrayList(u8),
gpa: std.mem.Allocator,

const CodeGen = @This();
ashen heart
#

do you free the slice returned by gen()?

half spire
#

It is from toOwnedSlice so no need from what i remember

#

Oh no, it was that

#

I know why it did happen: i was using the arena allocator before

restive moth
#

That's why it says "toOwned": it means that you now own that memory and are responsible for freeing it.

ashen heart