> ## Documentation Index
> Fetch the complete documentation index at: https://hypotenuse.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory Management in C△: allocate, autoremove, and Robbery

> Learn how C△ gives you full control over heap memory through manual allocate/free, automatic autoremove, and safe ownership transfer via Robbery.

<Warning>
  **Partial implementation.** Only `allocate` (including its custom-size syntax) and `free` are supported by the current Hypotenuse Compiler. `autoremove` and Robbery are not yet implemented. See [Compiler Status](/reference/compiler-status).
</Warning>

C△ gives you full control over memory while adding safer, more expressive tools on top of raw C heap management. Instead of reaching directly for `malloc` and `free`, you have three distinct mechanisms at your disposal: manual allocation with `allocate` and `free`, automatic deallocation with `autoremove`, and ownership transfer through Robbery. Together, they let you write systems code that is both precise and resistant to common memory bugs.

## Stack vs Heap

Variables you declare normally live on the stack and are reclaimed automatically when their enclosing scope exits. To keep data alive beyond a scope — or to allocate large buffers — you put it on the heap using the `allocate` keyword.

| Location | How                         | Notes                                      |
| -------- | --------------------------- | ------------------------------------------ |
| Stack    | Normal variable declaration | Freed automatically on scope exit          |
| Heap     | `allocate` keyword          | Must be freed manually or via `autoremove` |

## `allocate` — Heap Allocation

Use `allocate` to place a variable or array on the heap. There are two syntax forms depending on whether you want an array of elements or a single variable with a specific byte size.

```c theme={null}
// Allocate an array of N elements
allocate int buffer[256];
allocate string names[10];

// Allocate a single variable with a custom byte size
allocate int x(64);   // one int backed by 64 bytes
```

| Syntax                  | Meaning                                               |
| ----------------------- | ----------------------------------------------------- |
| `allocate int buf[256]` | Array of 256 `int` elements on the heap               |
| `allocate int x(64)`    | Single variable allocated with a 64-byte backing size |

<Note>
  Custom byte sizes specified with the parenthesis form are bounds-checked at compile time. If the requested size is incompatible with the declared type, the compiler reports an error before generating any code.
</Note>

## `free` — Manual Deallocation

Call `free` to release the heap memory you allocated with `allocate`. The pointer is invalidated immediately after the call.

```c theme={null}
allocate int x(8);   // allocate 8 bytes
x = 42;
free(x);             // release the allocation
```

<Warning>
  Forgetting to `free` a heap variable is a memory leak. If the allocation does not need to outlive the current scope, use `autoremove` instead so the compiler handles deallocation for you.
</Warning>

## `autoremove` — Automatic Heap Deallocation

Prefix `allocate` with `autoremove` and the compiler's simulation pass takes responsibility for freeing the memory. The pass performs static analysis to find the last use of the variable and inserts a `free` call at exactly that point during code generation. You may still free the pointer at any point, as long as it's not being used before its last use.

```c theme={null}
autoremove allocate int buf[512];
// ... use buf freely ...
// free is inserted automatically after the last use
```

<Tip>
  Prefer `autoremove` whenever you allocate memory that does not need to outlive the current scope. You get heap allocation with zero manual bookkeeping and zero runtime overhead — the `free` is woven in at compile time unless manually done.
</Tip>

Because the simulation pass runs before code generation, there is no runtime cost for this analysis. The emitted C code contains an ordinary `free` call placed at precisely the right line.

## Robbery — Ownership Transfer

Robbery handles the case where an `autoremove` variable is about to be freed but another pointer still needs its memory. When a second pointer takes the address of an `autoremove` variable at the point the original would drop, the new pointer inherits ownership and becomes a plain heap variable — one that you manage manually or hand off to another `autoremove` binding.

```c theme={null}
autoremove allocate int data[100];

// data is about to reach its last use — backup steals ownership
int* backup = &data;

// backup is now a plain heap variable; data is gone
// no double-free, no dangling pointer
// no need to free the robbed variable
```

The simulation pass validates every robbery before emitting code. If the transfer would create a use-after-free or a double-free, the compiler rejects the program with a clear diagnostic. You will never need to free a robbed variable when programming.

## Lifecycle Summary

The three memory flows map directly onto the three mechanisms:

```text theme={null}
[allocate]  →  [use]  →  [free]
    ↑ manual: you call free yourself

[autoremove allocate]  →  [use]  →  [auto-free at last use]
    ↑ simulation pass: compiler inserts free at compile time

[autoremove]  →  [robbery]  →  [plain heap variable]
    ↑ ownership transfer: new pointer takes over, original is gone
```

## Rules & Gotchas

<Accordion title="Common memory mistakes to avoid">
  * Do not double-free a variable after it has already been freed
  * Do not try to access an already freed portion of memory
  * Avoid leaks in memory as much as possible and try to use robbery to aid in this
</Accordion>
