Pitfalls
Pitfalls
Grouped by what breaks.
Lifetime
- A raw pointer into the managed heap is valid only until the next collection.
&T,opaque, andcstrare untracked. An object reachable only through one will be reclaimed.- A raw C string cannot be relabeled into a managed
string; it points at memory the collector does not own. Copy it withruntime::create_managed. - Anything the OS or a library tracks by address must be
malloc'd, not managed: socket handles, TLS contexts, thread bookkeeping. - A managed object's fields are written after its allocation returns, so a collection in between must not see garbage. The allocator zeroes the payload for exactly this reason; do not defeat it by handing out uninitialized memory.
Threads
- Every blocking call from an attached thread must be bracketed, or the process deadlocks silently.
- No GC operation while parked.
- No GC operation while holding a lock.
- A callback fired from a parked event loop must unpark before running managed code, and re-resolve any managed pointer through its handle.
- Every thread touching managed memory must attach from inside itself and detach when done.
- Killing a thread outright can leave a lock held or an allocation half-finished. Use cooperative cancellation.
Build and link
- There is no header dependency tracking. Editing a
.hdoes not rebuild the.cfiles that include it. Touch the sources or clean. - A per-platform source file must compile to nothing on other platforms, because every listed source is compiled for every target.
- Archives must follow the objects that reference them.
- Symbol names are not mangled, so two packages exporting the same name collide.
- Duplicated headers across packages can drift apart silently. Prefer one copy in one package and include it.
FFI
- A declaration without
p_fnorp_varis invisible, with no error. - Reserved words cannot name a parameter, function, or variable.
fn,in, andarchcatch people most often. - Raw
*is rejected; usep_gc(T),p_gc_opaque, orp_opaque. p_gcsafegoes before the return type.- A sibling
.pekofile shadows a.peko.hof the same name. - Omitting
p_gcsafeon a function that can allocate or block is a silent correctness bug, not a compile error.
Language
- The excluded branch of a
platformorarchblock is not type-checked. - An unknown platform name in such a block produces no diagnostic; it just never matches.
danger_castbetween non-numeric types emits no instruction. It is a relabel.constant<T>on a non-literal is also a relabel.- Pointer arithmetic does not exist.
When something is already wrong
Run the suspect workload under PEKO_GC_STRESS=1 to force a collection at every
allocation. A corruption that appears once an hour becomes reproducible, and the
crash moves close to its cause. PEKO_GC_VERIFY adds a mark-completeness check
on top.
If a crash lands inside a method dispatch on an object unrelated to your change, suspect a stale managed pointer held across an allocating call.