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.
#Free memory allocated from c
1 messages · Page 1 of 1 (latest)
[*:0]u8 should implicitly cast to ?*anyopaque, so you can pass it to std.c.free without casting
alternatively, you can use std.heap.c_allocator.free() on the slice
I'm trying to cast the slice [:0]const u8 not the c string itself
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
if c returned [*:0]u8 then you can keep it as [:0]u8 instead of [:0]const u8
That's what I was gonna try to do just now
See if it works as a normal [:0]u8 not const
how would you know if the c_allocator freed the memory or not?
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
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
Ok
Cause it still isn't going down
If I keep pressing the button it keeps going up
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;
}
}
is the iface ever freed?
iface_new probably allocates a new one, and then it won't get freed until it is unref'd
Yea probably that
also every call to xwii_monitor_poll needs its return value freed, not just the last one
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
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
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
alternatively:
var ent: ?[*:0]u8 = null;
for (0..id) |i| {
if(ent) |prev_ent| std.c.free(prev_ent);
ent = c.xwii_monitor_poll(monitor);
}
Yea that too