#Free memory allocated from c

1 messages · Page 1 of 1 (latest)

sterile nexus
#

I'm using an external c library that allocates a string ([*:0]u8) for you that you need to free yourself. I take that string and convert it to a slice ([:0]const u8) using std.mem.span() and I need to free the string so it doesn't leak. I tried using std.c.free(), but that takes a ?*anyopaque and I don't know how to cast the slice to that.

lime drum
#

alternatively, you can use std.heap.c_allocator.free() on the slice

sterile nexus
#

I'm trying to cast the slice [:0]const u8 not the c string itself

lime drum
#

.ptr

#

theslice.ptr will be [*:0]u8 and then that should implicitly cast

sterile nexus
#

Alright, thanks

#

The slice.ptr returns a [*:0]const u8 which std.c.free doesn't like, and the c_allocator.free on the slice also doesn't seem to work, and doesn't seem to free the mem

lime drum
sterile nexus
#

That's what I was gonna try to do just now

#

See if it works as a normal [:0]u8 not const

lime drum
#

how would you know if the c_allocator freed the memory or not?

sterile nexus
#

System monitor shows the memory going up on the process whenever I click the button that calls the C lib that allocates the string and is also supposed to free it when it defers to the end of the if (button) scope

lime drum
#

I don't know if free() ever returns the pages back to the operating system or if it just marks them for reuse by malloc()

#

so you might not see memory go down, but if you were to allocate another large thing it shouldn't go up

sterile nexus
#

Ok

#

Cause it still isn't going down

#

If I keep pressing the button it keeps going up

lime drum
#

ok so then something isn't getting freed properly

#

(assuming the button calls free)

sterile nexus
#

The button calls the C lib that allocates it, uses it, then frees it

#
if (rg.guiButton(.{ .x = 56, .y = 0, .width = 128, .height = 24 }, "Connect Wiimote") != 0) {
    const dev = try wiimote.getDevFromId(1);
    defer std.c.free(dev.ptr);
    wiimote_iface = try wiimote.getIface(dev);

}

Rg is raygui, I'm using the nik-nok Raylibzig and xwiimote

#
pub fn getDevFromId(id: u8) ![:0]u8 {
    const monitor = c.xwii_monitor_new(false, false);
    if (monitor == null) {
        std.debug.print("Cannot create monitor\n", .{});
        return error.CannotCreateMonitor;
    }

    var ent: ?[*:0]u8 = undefined;
    for (0..id) |_| {
        ent = c.xwii_monitor_poll(monitor);
    }

    c.xwii_monitor_unref(monitor);

    std.debug.print("ent: {} = {any}\n", .{ @TypeOf(ent), ent });

    if (ent) |ret| {
        return @as([:0]u8, std.mem.span(ret));
    }
    else {  //if (ent == null) {
        std.debug.print("Cannot find device with number #{}\n", .{id});
        return error.WiimoteNotFound;
    }
}
#
pub fn getIface(dev: [:0]const u8) !*Iface {
    var iface: ?*Iface = undefined;
    _ = c.xwii_iface_new(&iface, dev);
    
    if (iface) |ret| {
        return ret;
    }
    else {
        return error.IfaceNull;
    }
}
lime drum
#

is the iface ever freed?

sterile nexus
#

I was thinking it was getting replaced

#

Not reallocated

lime drum
#

iface_new probably allocates a new one, and then it won't get freed until it is unref'd

sterile nexus
#

Yea probably that

lime drum
sterile nexus
#

The monitors have an internal ref counter that decreases when you call monitor_unref(monitor) with them that automatically frees them when it has zero refs, and they get created with one ref

lime drum
#

but ent has to be freed right?

#
    var ent: ?[*:0]u8 = undefined;
    for (0..id) |_| {
        ent = c.xwii_monitor_poll(monitor);
    }

if id is 5, you call ent 5 times but only free the last one

sterile nexus
#

That's the string I was originally freeing

#

Oh you're right about the if I'd is 5

#

That's not my problem now but that is another one

#

I just had I'd=1

#

Well spamming the button isn't having the memory go up anymore

#
    var ent: ?[*:0]u8 = undefined;
    for (0..id) |i| {
        ent = c.xwii_monitor_poll(monitor);
        if (i != id-1) std.c.free(ent);
    }
#

I'm not good with memory management I come from lua

lime drum
sterile nexus
#

Yea that too