For the complete Mojo documentation index, see llms.txt. Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).
alloc
Implements layout-aware memory allocation and deallocation.
This module provides the alloc and dealloc functions together with a
Layout descriptor that expresses the size and alignment of an allocation at
the call site, keeping ownership and layout information explicit and
co-located.
Allocations are represented by two explicitly destroyed (@explicit_destroy)
owning handles, so the compiler forces every allocation to be released on all
paths — either by passing it to dealloc or by taking the raw pointer with
unsafe_leak():
Allocation[T]: the handle returned byalloc. It bundles the owning pointer with theLayoutit was allocated with, so the element count and alignment needed to free the storage travel with the pointer.ThinAllocation[T]: a bare owning handle that carries only the pointer, with noLayout. It makes a good storage field for a container that already tracks its own capacity (such asList); pair it back with aLayoutviaunsafe_with_layoutto deallocate.
Examples:
Allocate, use, and free storage through the Allocation returned by alloc:
from std.memory.alloc import alloc, dealloc, Layout
from std.memory import destroy_n
var allocation = alloc(Layout[String](count=4))
var ptr = allocation.unsafe_ptr()
# initialize the memory
for i in range(allocation.layout().count()):
(ptr + i).init_pointee_move("🔥")
# print the values
for string in allocation.unsafe_span():
print(string) # prints "🔥"
# deinitialize the values
destroy_n(allocation.unsafe_ptr(), allocation.layout().count())
# deallocate the memory
dealloc(allocation^)
Drop the Layout with into_thin to keep only the bare ThinAllocation handle,
then re-attach a Layout with unsafe_with_layout to deallocate:
from std.memory.alloc import alloc, dealloc, Layout
var layout = Layout[Int64].single()
var thin = alloc(layout).into_thin()
dealloc(thin^.unsafe_with_layout(layout))
Memory safety:
Because Allocation and ThinAllocation are @explicit_destroy types, the
compiler catches the three classic allocation bugs at compile time, instead of
leaving them as runtime hazards.
An accidental leak is rejected: the compiler requires every Allocation to be
destroyed on every path, including error paths. If an intervening operation can
raise, skipping the dealloc, that is an error (whose message includes the
guidance from @explicit_destroy):
from std.memory import alloc, dealloc, Layout
def process() raises:
var allocation = alloc(Layout[Int].single())
might_raise() # ERROR: 'allocation' abandoned without being explicitly destroyed: ...
dealloc(allocation^)
A double-free is rejected: dealloc consumes the handle, so a second dealloc
is a use of an uninitialized value:
from std.memory import alloc, dealloc, Layout
def main():
var allocation = alloc(Layout[Int].single())
dealloc(allocation^)
dealloc(allocation^) # ERROR: use of uninitialized value 'allocation'
A use-after-free is rejected: a pointer obtained from an Allocation borrows
from it, so it cannot be accessed once the handle has been consumed:
from std.memory import alloc, dealloc, Layout
def main():
var allocation = alloc(Layout[Int].single())
var ptr = allocation.unsafe_ptr()
dealloc(allocation^)
print(ptr[]) # ERROR: potential indirect access to uninitialized value 'allocation'
Structs
-
Allocation: An owning handle to a heap allocation ofTtogether with itsLayout. -
Layout: Describes the shape of a memory allocation for elements of typeT. -
ThinAllocation: An owning handle to a heap allocation ofT, without itsLayout.