IMPORTANT: To view this page as Markdown, append `.md` to the URL (e.g. /docs/manual/basics.md). For the complete Mojo documentation index, see llms.txt.
Skip to main content
Version: 1.0.0b2
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 by alloc. It bundles the owning pointer with the Layout it 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 no Layout. It makes a good storage field for a container that already tracks its own capacity (such as List); pair it back with a Layout via unsafe_with_layout to 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 of T together with its Layout.
  • Layout: Describes the shape of a memory allocation for elements of type T.
  • ThinAllocation: An owning handle to a heap allocation of T, without its Layout.

Functions

  • alloc: Allocates owned storage for layout.count() elements of T.
  • dealloc: Deallocates the storage owned by an Allocation.