Files
cproof-context/patterns/memory.md
jabber.developer2 22977846a3 docs: split context into layered, agent-oriented files
Replace the single file-structure.md with a stratified layout designed
for AI/agent skill consumption: tables and concrete identifiers over
prose, files loaded on demand, content separated by churn rate.

Layers:
- architecture/  stable structural reference (overview, source-map,
                 test-map, data-flow)
- patterns/      memory, commands, autocomplete, events, xmpp,
                 encryption, ui, plugins
- testing/       unit-tests, stubs, functional-tests, bench
- build/         local, docker, ci
- playbooks/     add-command, add-test, add-autocomplete,
                 add-event-handler, add-encryption
- gotchas.md     append-only dated entries (seven seed entries)
- wip/           branch-specific notes; deleted on merge to master

Stable layers describe cproof on master only. In-flight feature
branches (currently feat/ai) get a single file under wip/.

INDEX.md is the entry map with churn labels; SKILL.md is the
always-loaded skill hint pointing to it.
2026-04-30 20:52:06 +03:00

2.7 KiB

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:

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.