# Memory management ## `auto_*` macros GCC/Clang `__cleanup__` attribute, declared in `src/common.h` (one exception: `auto_jid` lives in `src/xmpp/jid.h` because it needs the `Jid` type). | Macro | Type | Cleanup | Use for | |---|---|---|---| | `auto_gchar` | `gchar*` | `auto_free_gchar()` | GLib strings (`g_strdup`, `g_strdup_printf`, etc.) | | `auto_gcharv` | `gchar**` | `auto_free_gcharv()` | GLib string arrays (`g_strsplit`, `g_strjoinv` arg) | | `auto_char` | `char*` | `auto_free_char()` | C strings (`strdup`, `malloc`'d) | | `auto_guchar` | `guchar*` | `auto_free_guchar()` | Unsigned char buffers (e.g. `g_base64_decode`) | | `auto_gfd` | `gint` | `auto_close_gfd()` | File descriptors held in a `gint` | | `auto_FILE` | `FILE*` | `auto_close_FILE()` | `FILE*` from `fopen` | | `auto_jid` | `Jid*` | `jid_auto_destroy()` | `Jid` structs (XMPP) | Place the macro **before** the type, like `gboolean`-style attribute: ```c auto_gchar gchar* msg = g_strdup_printf("hello %s", name); auto_gcharv gchar** parts = g_strsplit(line, " ", -1); ``` The cleanup runs at scope exit, including early returns. Do **not** call the matching `g_free`/`g_strfreev`/`fclose` manually — that double-frees. ## Manual cleanup helpers In `common.h`: | Macro | Behaviour | |---|---| | `FREE_SET_NULL(ptr)` | `free(ptr); ptr = NULL;` (use for `malloc`'d) | | `GFREE_SET_NULL(ptr)` | `g_free(ptr); ptr = NULL;` (use for GLib-allocated) | Use these when the pointer is a struct field that must remain accessible after the free (so a later `if (x->p)` is safe). ## GLib free-function reference | Allocator | Free with | |---|---| | `g_strdup`, `g_strdup_printf`, `g_strconcat`, ... | `g_free` (or `auto_gchar`) | | `g_strsplit`, `g_strdupv` | `g_strfreev` (or `auto_gcharv`) | | `g_list_*` of allocated items | `g_list_free_full(list, free_fn)` | | `g_hash_table_new[_full]` | `g_hash_table_destroy` (uses key/value destroy fns if supplied) | | `g_base64_decode` | `g_free` (or `auto_guchar`) | | `g_key_file_*` | `g_key_file_free` | **Common pitfall:** mixing `g_free` and `free`. GLib uses its own allocator shim; never cross the boundary. If you got the buffer from a GLib function, free it with the matching GLib function. **Common pitfall:** `g_strsplit` returns `gchar**` — free with `g_strfreev`, not `g_free`. (See `gotchas.md`.) ## Adding a new `auto_*` 1. Declare cleanup function: `void auto_close_foo(Foo** p);` 2. Define the macro: `#define auto_foo __attribute__((__cleanup__(auto_close_foo)))` 3. Place both in the header that owns the type — `common.h` for project-wide, the type's own header otherwise. 4. The cleanup must tolerate `NULL` and idempotent re-entry; assign `*p = NULL` inside if you keep the variable accessible after free.