Zig: Allocator seg fault

Created on 9 Jun 2018  路  5Comments  路  Source: ziglang/zig

I'm not exactly sure what is going on here. If you run zig test src/parse.zig in https://github.com/isaachier/zig-parser-generator the test crashes. I have used gdb to track this into the first insertion into the RuleSet hash map. The line it crashes on involves calling an arena allocator to allocate space for the map. The problem is, there is no error message here or much else to help me debug. Sorry to paste a link, but not sure what else to do here.

Most helpful comment

@andrewrk, i think this is because arena is copied in the init function, so this will be solved by #287.

All 5 comments

Seems like the allocFn for the HashMap's allocator isn't set to a valid address for some reason.

(lldb) p self->allocFn
(Error![]u8 (*)(Error![]u8 *, StackTrace *, Allocator *, unsigned long, unsigned int)) $3 = 0x0000000000000001

Backtrace for reference:

* thread #1, name = 'test', stop reason = signal SIGSEGV: invalid address (fault address: 0x1)
  * frame #0: 0x0000000000000001
    frame #1: 0x0000000000208563 test`Allocator_alignedAlloc at mem.zig:71
    frame #2: 0x00000000002083e3 test`Allocator_alloc at mem.zig:63
    frame #3: 0x0000000000207b49 test`HashMap(hm=0x00007fffffffde58)_initCapacity at hash_map.zig:167
    frame #4: 0x00000000002067a8 test`HashMap(hm=0x00007fffffffde58)_put at hash_map.zig:94
    frame #5: 0x0000000000206273 test`RuleSet_put(self=0x00007fffffffde18) at grammar.zig:52
    frame #6: 0x0000000000205347 test`Parser_parseRule(self=0x00007fffffffdde8) at parse.zig:172
    frame #7: 0x000000000020467b test`Parser_parse(self=0x00007fffffffdde8) at parse.zig:163
    frame #8: 0x0000000000203b4a test`parseInputFile(allocator=0x0000000000241000) at parse.zig:19
    frame #9: 0x000000000020367f test`parse input at parse.zig:178
    frame #10: 0x0000000000224ef8 test`main at test_runner.zig:11
    frame #11: 0x0000000000224cfb test`callMain at bootstrap.zig:102
    frame #12: 0x0000000000224c69 test`callMainWithArgs(argc=1) at bootstrap.zig:76
    frame #13: 0x0000000000224a68 test`posixCallMainAndExit at bootstrap.zig:70
    frame #14: 0x0000000000224910 test`_start at bootstrap.zig:43

I noticed at one point the arena allocator had its freeFn function pointer set to 0x1. Is it possible that realloc triggers a free that is invalid in an arena?

A little digging didn't help too much, but the failure of a new assertion I added is a bit disturbing.

    pub fn init(allocator: *Allocator) RuleSet {
        var arena = ArenaAllocator.init(allocator);
        return RuleSet{
            .arena = arena,
            .map = RuleMap.init(&arena.allocator),
        };
    }

    pub fn deinit(self: *RuleSet) void {
        self.arena.deinit();
    }

    pub fn put(self: *RuleSet, name: []const u8) !*Rule {
        var rule = try Rule.init(&self.arena.allocator, name);
        std.debug.warn("put: {}\n", rule.name.toSliceConst());
        std.debug.assert(self.map.allocator == &self.arena.allocator);
        ...

The map allocator is changing somewhere between init and put, but I have no idea how.

@andrewrk, i think this is because arena is copied in the init function, so this will be solved by #287.

Yeah that's right. The problem is here:

        var arena = ArenaAllocator.init(allocator); // memory for arena.allocator is in this stack frame
        return RuleSet{
            .arena = arena,
            .map = RuleMap.init(&arena.allocator), // returning a pointer that is about to become invalid
        };

After #287 and after we have the ability to mark a field as "fixed" this would be a compile error, and it would be resolved by using the no-copy semantics.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andrewrk picture andrewrk  路  3Comments

bheads picture bheads  路  3Comments

andrewrk picture andrewrk  路  3Comments

bronze1man picture bronze1man  路  3Comments

andrewrk picture andrewrk  路  3Comments