#access of union field 'Pointer' while field 'Struct' is active

1 messages · Page 1 of 1 (latest)

rotund linden
#

Hello amazing people!
You friendly zig-n00b is stuck while understanding this error:

/zig/zig-linux-x86_64-0.11.0-dev.2297+28d6dd75a/lib/std/mem/Allocator.zig:296:45: error: access of union field 'Pointer' while field 'Struct' is active
    const Slice = @typeInfo(@TypeOf(memory)).Pointer;

The code I am testing is this:

pub const TokenKvp = struct {
    allocator: *std.mem.Allocator,
    key: []u8,
    value: []u8,

    pub fn init(allocator: *std.mem.Allocator, key: []const u8, value: []const u8) !TokenKvp {
        var self = TokenKvp{
            .allocator = allocator,
            .key = try allocator.dupe(u8, key),
            .value = try allocator.dupe(u8, value),
        };
        return self;
    }

    pub fn deinit(self: *TokenKvp) void {
        self.allocator.free(self.key);
        self.allocator.free(self.value);
    }
};

pub const Entity = struct {
    allocator: *std.mem.Allocator,
    kvps: std.ArrayList(TokenKvp),
    line: usize,

    pub fn init(allocator: *std.mem.Allocator, line: usize) !Entity {
        var kvpList = std.ArrayList(TokenKvp).init(allocator.*);

        var self = Entity{
            .allocator = allocator,
            .kvps = kvpList,
            .line = line,
        };

        return self;
    }

    pub fn addEntity(self: *Entity, key: []const u8, value: []const u8) !void {
        var kvp = try TokenKvp.init(self.allocator, key, value);
        try self.kvps.append(kvp);
    }

    pub fn deinit(self: *Entity) void {
        for (self.kvps.items) |*kvp| {
            kvp.deinit();
        }
        self.allocator.free(self.kvps);
    }
};

test "kvp testing" {
    var testingAllocator = std.testing.allocator;
    var value: []const u8 = "value";
    var key: []const u8 = "key";
    var entity = try Entity.init(&testingAllocator, 0);
    try entity.addEntity(key, value);
    defer entity.deinit();
}
#

I am asking your help since this is not the first time I found that problem and I would like to understand what it is, and understand how I could solve this. Any kind help is highly appreciated. I'm doing my best to learn... but sometimes I get stuck on these problems and I need some help...

spring stone
#

You're probably calling .free on some datastructure which you're not allowed to.

#

Use .deinit

dreamy dirge
#

The issue is in this line:
self.allocator.free(kvps)
The function allocator.free is specifically for freeing blocks of memory allocated through alloc. Types which manage their own memory generally have a deinit method

#

So that line should be replaced with kvps.deinit()

rotund linden
#

don't you have a memory leak?
I am using allocator.dupe(u8, key), to create the key and same for value

dreamy dirge
#

The loop is correct

#

It's purely the free(kvps) line that's the problem

rotund linden
#

ah damn!

#

now I saw it

#

I am such an idio

#

:_(

dreamy dirge
#

Also of note here: you don't need to pass around pointers to allocators! std.mem.Allocator already contains a pointer, so can (and should) be passed by value. Allocator used to work a bit differently, so you might have been looking at some old documentation or something

rotund linden
#

ooooh thanks for this tip!

spring stone
#

You can pass an allocator to the methods that require one instead

#

(Like ArrayListUnmanaged does for example)

rotund linden
#

you're definitely right, so I could just have it in the Entity!

dreamy dirge
rotund linden
#

ah when compiling only then! I tried when testing and it did not give any further output

#

zig test I mean

spring stone
#

Same goes for the array list btw. You can also use ArrayListUnmanaged which then requires an allocator to be passed into their functions.