Part 15: Memory
Until now every value had a size the compiler knew and a home it chose. This part opens the box underneath: pointers that hold addresses, memory you ask for while the program runs, and the layout of the bytes themselves. It starts with the rawest tools, where every rule is yours to keep, and ends with allocators that keep most of those rules for you — so by the end you know both what they do and why they exist.
What you will learn
- Taking an address with
@, reaching through it with*, and the difference between*Tand*var T. - Returning extra answers through an out-parameter, and why a fallible is usually better.
- Asking for memory with
Alloc, clearing it withZeroand returning it withFree. - Pointer arithmetic, and turning a pointer and a count into an ordinary slice with
p[..n]. - Optional pointers
(*T)?versus pointers to optionals*T?, and whynullis notnone. - How big a type is and how it is aligned, and the padding a struct carries.
- Unions, which lay several members over the same bytes.
- The
Allocatorinterface, and four ways to stand behind it:SystemAllocator,Arena,FixedBufferandPool— plusBox<T>, which owns one allocated value. - Wiping a secret with
Zeroize, a clear the compiler never removes.
The allocator family
flowchart LR
code["your code,<br/>written against Allocator"] --> iface{{"Allocator<br/>Allocate · Deallocate · Reallocate"}}
box["Box<T><br/>owns one value"] --> iface
iface --- sys["SystemAllocator<br/>pages from the system"]
iface --- arena["Arena<br/>a moving marker; Reset frees all"]
iface --- fixed["FixedBuffer<br/>storage you own; a hard limit"]
iface --- pool["Pool<br/>fixed-size blocks, reused"]
sys -. "backs" .-> arena
sys -. "backs" .-> poolCode that takes an Allocator works with any of the four. SystemAllocator asks the operating system and is usually the one an arena or a pool draws its large blocks from; FixedBuffer draws on nothing but the storage you give it.
Lessons
| Lesson | What you will learn | |
|---|---|---|
| 15.1 | Pointer | the difference between *T and *var T, and taking an address with @ |
| 15.2 | Out parameter | return extra information through a pointer parameter |
| 15.3 | Raw memory | allocate, use and free memory by hand (Alloc, Zero, Free) |
| 15.4 | Pointer arithmetic | step a pointer through memory one element at a time |
| 15.5 | Pointer slice | turn a pointer and a length into a slice |
| 15.6 | Optional pointer | *T? and (*T)?: a pointer to an optional, or an optional pointer |
| 15.7 | Layout | how big a type is and how it is aligned: sizeof and alignof |
| 15.8 | Union | overlay one piece of storage with several types, and why that needs care |
| 15.9 | Allocator | allocate through the Allocator interface instead of straight from the system |
| 15.10 | Box | own one value allocated on the heap |
| 15.11 | Arena | allocate many values and free them all at once |
| 15.12 | Fixed buffer | allocate from a buffer you provide |
| 15.13 | Pool | reuse fixed-size blocks instead of allocating new ones |
| 15.14 | Zeroize | clear sensitive memory explicitly |
Before you start
This part leans on much of what came before. Pointers build on Reference from Part 6; allocators report failure with the fallibles of Part 9: Errors; cleaning up relies on Destructor, Move and Defer from Part 11: Ownership; and Allocator is used as in Interface value from Part 12: Interfaces. Each lesson's package is in the Examples repository's Memory/ folder:
cd Examples/Memory/Pointer
rux run
After this part
Part 16: Numbers looks at numbers in depth — wide integers, limits, bit operations, checked and wrapping arithmetic. After Part 16 you are ready for the checkpoint projects Circle and Quadratic. Then Part 17: Collections puts this part to work: its containers take an Allocator and grow by asking it for memory.
For the full rules, see Pointers, Pointer arithmetic, Slices and pointers and Unions in the Rux Reference, and the Memory package in the API reference.