Manual memory
Core exposes allocation and release as explicit language operations while deriving sizes and alignment from the compilation target.
Stack values
Ordinary local values use automatic stack storage. Struct construction returns a value directly and does not allocate heap memory. Stack arrays destroy their struct elements when the allocation scope exits, then reclaim their storage.
Vector3 position = Vector3 { 1.0f, 2.0f, 3.0f };
Typed heap allocation
new T(...) computes the target ABI size and alignment of T, allocates storage, constructs the value and returns T*. A failed new traps; it never returns a null pointer.
Vector3* position = new Vector3(1.0f, 2.0f, 3.0f);
position->Y = 8.0f;
Brace construction may also be used directly in a heap allocation.
Vector3* origin = new Vector3 { 0.0f, 0.0f, 0.0f };
Raw allocation
malloc(size) returns an untyped void* block with the platform's default alignment. malloc(size, alignment) requests a power-of-two alignment, and calloc(count, size) returns a default-aligned block whose bytes are zero. Sizes and alignment use nuint; ordinary non-negative integer literals are accepted directly.
void* bytes = malloc(1024);
void* cacheLine = malloc(256, 64);
byte* zeroed = cast<byte*>(calloc(32, sizeof(byte)));
if (bytes == null) return;
Raw allocation does not construct objects. malloc leaves bytes uninitialized. Invalid alignment, size overflow, multiplication overflow in calloc, and allocation failure return null without trapping. The aligned and unaligned forms share one Xenon allocation ABI and may be released through the same free operation.
Lifetime and storage release
free(pointer) releases only the allocation. It never invokes a destructor, performs virtual dispatch, or destroys array elements. Use it for raw bytes or after every live object in manually managed storage has already been ended.
free(bytes);
free(cacheLine);
free(zeroed);
delete(pointer) is the destructor-aware operation for typed heap values. It invokes the complete destructor selected by the pointer type (including virtual dispatch), then releases the allocation. For arrays it destroys elements in reverse linear order before releasing storage.
delete(position);
delete(origin);
Resource[] values = new Resource[8];
delete(values);
delete(voidPointer) is rejected because an untyped address has no destructor type; cast to the correct typed pointer first only when a live object of that type is really present, or use free for storage-only release. Both operations accept null as a no-op. Never release a stack address, an interior pointer, an allocation obtained from an incompatible external allocator, or the same allocation twice.
A raw pointer is non-owning: its type neither proves allocation origin nor chooses who must release it. unique<T> and shared<T> provide compiler-managed ownership and automatically perform the equivalent destructor-plus-deallocation sequence. Never pass an ownership handle itself to free or delete.
Concurrent allocation
new, malloc, calloc, free and delete use the selected platform's thread-safe native allocator through Xenon's shared allocation ABI. Independent objects and arrays may therefore be allocated and released simultaneously by different native threads. An allocation may also be created on one thread and released on another when the program transfers responsibility safely.
Allocator safety does not synchronize the allocated value. The program must still arrange exactly one release, keep the allocation alive while it is accessed, and synchronize concurrent reads or writes to its contents according to the memory model. Xenon does not expose custom allocator interfaces or allocator-specific concurrency controls.