#How to "hold" a debug allocator

1 messages · Page 1 of 1 (latest)

sleek lantern
#

How do you hold a debug allocator, so that you can clean it up only if you need to? I am trying to do someting like this:

var dba: ?std.heap.DebugAllocator = null;

pub export fn setup() void {
    std.debug.print("Starting android.", .{});
    if (builtin.mode == .Debug) {
        dba = std.heap.DebugAllocator(.{}){};
        do_stuff(dba.allocator());
    } else {
        do_stuff(std.heap.smp_allocator);
    }
}

I understand enougn to know that this error means that I am being retruned a function not a struct, but I don`t know exactly what the right way to fix this is:

src/main.zig:2:19: error: expected type 'type', found 'fn (comptime heap.debug_allocator.Config) type'
var dba: ?std.heap.DebugAllocator = null;

Thanks!

polar wing
#

The bigger question is why you want to hold the debug allocator?
You can simply defer _ = db.deinit() at the initialisation site to clean it up.

If you want to have an allocator to clean up your allocated objects, you should call the allocator() method on the object returned from the .init of the Debug Allocator. This returns an std.mem.Allocator type which is very commonly used.

#

It's worth noting that the stdlib is moving towards a pattern of not holding allocators in structs

sleek lantern
#

The debug allocator needs to live beyond the return of the setup function.

#

The cleanup is in a different function.

#

(more specifically)

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])

and

void SDL_AppQuit(void *appstate, SDL_AppResult result)
polar wing
#

You're doing interop with C code?

sleek lantern
#

Probably, depends on what you mean in interop. I am drawing things with SDL, but I am not writing C code.

polar wing
#

Yeah, that's a bit out of my pay grade. I don't really touch game dev stuff

sleek lantern
#

All I want to do is cleanup a debug allocator

#

So I need to store it in a variable.

polar wing
#

Link the full code snippet, I need context

sleek lantern
#

Here is the same sample in my question above, but not simplified.

var dba: ?std.heap.DebugAllocator = null;

/// Handle SDL_AppInit.
pub export fn my_startup(_: c_int, _: [*:null]const ?[*:0]const u8) void {
    std.debug.print("Starting android.", .{});
    if (builtin.mode == .Debug) {
        dba = std.heap.DebugAllocator(.{}){};
        app.app_context = try app.AppContext.create(dba.allocator(), null);
    } else {
        app.app_context = try app.AppContext.create(std.heap.smp_allocator, null);
    }
}

/// Handle SDL_AppQuit.
pub export fn my_quit(_: c_uint) void {
    app.app_context.?.destroy();
    std.debug.print("Exiting android.", .{});
    if (dba) |a| {
        a.deinit();
    }
}
#

Just imagine you have a main function in normal zig code, but you have to split the start and end of your main function into two separate functions.

polar wing
#

You can deinit the debug allocator with a defer keyword at the call site

#

That'll span the "main" block

sleek lantern
#

Oh? Wouldnt the deinit be triggeed once the startup function exits?

polar wing
#

What I mean is this:

sleek lantern
#

And how do you guarantee the dba variable lives until game exit? even if its not deinitilised?

#

Cool....

polar wing
#
pub fn main() !void {
    var debug = std.heap.DebugAllocator(.{}).init;
    const allocator = debug.allocator();
    defer _ = debug.deinit();
    
    //From this point, you can use the allocator object freely in your code. 
    
}```
sleek lantern
#

That will clean up the allocator as soon as the function returns. I need the debug allocator to live beyond the return of the function.

#

(If your curious as to why, the reason is because SDL itself is the "main" function. SDL calls the zig code so that it can startup and later on so it can shutdown.)

polar wing
#

Hmm, so SDL calls your Zig function to initialise its state, and calls a shutdown to clean up

#

Change the type of the dba

#

To
var dba:std.heap.DebugAllocator(.{})

#

Let me know if it works

sleek lantern
#

Yes, that solves it. That is interesting to me, I didn't initially think to try this because it feels like passing a variable to a variable "placeholder" so to speak. Thanks!!

polar wing
#

That's because the DebugAllocator is actually a function that returns a type when it's called

#

You store that type, and then call init to initialise it.

#

Have a look at the source code