How to free memory allocated by C library? (libmariadb.so)

I am trying to use the MariaDB C connector in zig, so I compiled the C library and added the following four lines to my build.zig which worked for the compilation.

    // contains mysql.h
    exe.addIncludePath(.{ .cwd_relative = "mariadb-connector/include/" });

    // contains mariadb_version.h
    exe.addIncludePath(.{ .cwd_relative = "mariadb-connector/build/include/" });

    // contains libmariadb.so
    exe.addLibraryPath(.{ .cwd_relative = "mariadb-connector/build/libmariadb/" });
    exe.linkSystemLibrary("mariadb");

And a simple main.zig

const std = @import("std");
const mysql = @cImport({
    @cInclude("mysql.h");
});

pub fn main() !void {
    const alloc = std.heap.c_allocator;

    const db = mysql.mysql_init(null);
    defer alloc.free(db);

    std.debug.print("{*}\n", .{db});
}

If I don’t put the defer alloc.free(db) it compiles and prints successfully. But I’m unsure how to free the db object, because as per the documentation it allocates memory you pass in NULL. How should I free that memory allocated in C?

Compilation error:

run
└─ run export_server_objects
   └─ zig build-exe export_server_objects Debug native 2 errors
/home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/mem/Allocator.zig:314:31: error: expected type '[]u8', found '[]align(8) allowzero u8'
    self.rawFree(non_const_ptr[0..bytes_len], log2a(Slice.alignment), @returnAddress());
                 ~~~~~~~~~~~~~^~~~~~~~~~~~~~
/home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/mem/Allocator.zig:314:31: note: '[]align(8) allowzero u8' could have null values which are illegal in type '[]u8'
/home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/mem/Allocator.zig:97:45: note: parameter type declared here
pub inline fn rawFree(self: Allocator, buf: []u8, log2_buf_align: u8, ret_addr: usize) void {
                                            ^~~~
referenced by:
    main: src/main.zig:10:21
    callMain: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/start.zig:524:32
    callMainWithArgs: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/start.zig:482:12
    main: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/start.zig:497:12
/home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/mem.zig:4117:14: error: type '[*c]cimport.struct_st_mysql' does not support field access
    if (slice.len == 0 and std.meta.sentinel(Slice) == null) return &[0]u8{};
        ~~~~~^~~~
referenced by:
    free__anon_4181: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/mem/Allocator.zig:308:35
    main: src/main.zig:10:21
    callMain: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/start.zig:524:32
    callMainWithArgs: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/start.zig:482:12
    main: /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/lib/std/start.zig:497:12
error: the following command failed with 2 compilation errors:
/home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/zig build-exe -freference-trace=256 -lmariadb -ODebug -I /home/cocoa/Work/Phanes/Issues/vf_control_datarec/mariadb-connector/include -I /home/cocoa/Work/Phanes/Issues/vf_control_datarec/mariadb-connector/build/include -L /home/cocoa/Work/Phanes/Issues/vf_control_datarec/mariadb-connector/build/libmariadb -Mroot=/home/cocoa/Work/Phanes/Issues/vf_control_datarec/src/main.zig -lc --cache-dir /home/cocoa/Work/Phanes/Issues/vf_control_datarec/.zig-cache --global-cache-dir /home/cocoa/.cache/zig --name export_server_objects --listen=-
Build Summary: 0/5 steps succeeded; 1 failed (disable with --summary none)
run transitive failure
└─ run export_server_objects transitive failure
   β”œβ”€ zig build-exe export_server_objects Debug native 2 errors
   └─ install transitive failure
      └─ install export_server_objects transitive failure
         └─ zig build-exe export_server_objects Debug native (reused)
error: the following build command failed with exit code 1:
/home/cocoa/Work/Phanes/Issues/vf_control_datarec/.zig-cache/o/f85d5de3071de86b836368d3f373b46c/build /home/cocoa/.local/bin/zig-linux-x86_64-0.13.0/zig /home/cocoa/Work/Phanes/Issues/vf_control_datarec /home/cocoa/Work/Phanes/Issues/vf_control_datarec/.zig-cache /home/cocoa/.cache/zig --seed 0x47a5db77 -Za41975842969f70c -freference-trace run

Don’t you need to call mysql_close() on the object returned from mysql_init() as documented:

Allocates or initializes a MYSQL object suitable for mysql_real_connect(). If mysql is a NULL pointer, the function allocates, initializes, and returns a new object. Otherwise, the object is initialized and the address of the object is returned. If mysql_init() allocates a new object, it is freed when mysql_close() is called to close the connection.

3 Likes

Yes I should have RTFM-ed better, thank you so much.

1 Like