Search docsSearch this language
Using C2Go
Release candidatev0.20260809.0-rc.5

These docs describe the current coordinated release candidate.

Using C2Go

GC-aware allocation

Allocate typed C objects on the Go heap and preserve their pointer layout.

gc_malloc allocates zeroed memory on the Go heap. Unlike ordinary C allocation, it accepts runtime type information so the collector knows which machine words contain pointers.

Allocate one record

#include <c2go.h>
#include <stddef.h>
#include <stdint.h>

struct managed Node {
    struct Node *next;
    int value;
};

struct Node *new_node(int value) {
    struct Node *node = gc_malloc(
        c2go_typeinfo(struct Node),
        sizeof(struct Node)
    );
    if (node == NULL) {
        return NULL;
    }
    node->value = value;
    return node;
}

c2go_typeinfo(struct Node) is a compiler builtin exposed as a macro. It produces the Go runtime type descriptor for that named managed record. You do not write or register the pointer bitmap by hand.

There is no matching free: the Go GC reclaims the object after it becomes unreachable.

Heap allocation is also the required rewrite when a value must outlive its C stack frame. Never store &local in this object; C2Go does not automatically move that local to the heap. See Stack escape safety.

Allocate an array

Use gc_malloc_array when pointer metadata must repeat for every element:

struct Node *nodes = gc_malloc_array(
    c2go_typeinfo(struct Node),
    sizeof(struct Node),
    count
);

The runtime repeats the element pointer bitmap across the allocation, analogous to allocating a Go slice backing array.

The current inline helper directly computes elem_size * count; it does not check multiplication overflow for the caller. For untrusted lengths, first validate count <= SIZE_MAX / elem_size and check the returned pointer for NULL.

Allocate a pointer-free blob

Passing NULL as type information creates memory that the GC does not scan for pointers:

unsigned char *bytes = gc_malloc(NULL, byte_count);

Only do this when the allocation will never contain managed pointers. Hiding a managed pointer inside a blob can let the referenced object become unreachable from the GC’s point of view.

Do not mix ownership models

Allocator World Release
gc_malloc / gc_malloc_array typed managed Go heap automatic GC
malloc / calloc / realloc c2go-libc unmanaged C-semantics storage free

Never call free on a typed Go-heap pointer, and do not assume a native library can retain a managed pointer indefinitely. If a native API takes ownership, use the allocator that API explicitly requires and copy the data, or design a stable handle boundary. c2go-libc’s malloc is not the host system malloc.

Type information constraints

c2go_typeinfo requires a named, complete record type. Anonymous records and reserved runtime identifiers are rejected. Packed or custom-aligned managed records produce warnings and target-specific generated layouts; prefer natural layout for portable public types.

Next, scale the same rules across multi-file projects and LTO.