Object allocation¶
Cairo has a few ways of storing an object in memory and getting a pointer to it (which can be used by other functions):
Memory segment allocation: The alloc() function can be used to create an arbitrary-length array.
Single item allocation: The new operator initializes a single item and returns a pointer to it.
Local variables: You can allocate a local variable and retrieve its address. See Accessing the values of the registers.
alloc()¶
The standard library function alloc()
may
be used to “dynamically” allocate a new memory segment (see Segments).
This segment can be used to store an array or a single element.
For example:
from starkware.cairo.common.alloc import alloc
func foo() {
let (struct_array: MyStruct*) = alloc();
// Set the first three elements.
assert struct_array[0] = MyStruct(a=1, b=2);
assert struct_array[1] = MyStruct(a=3, b=4);
assert struct_array[2] = MyStruct(a=5, b=6);
return ();
}
The “new” operator¶
The new
operator takes an expression and pushes it onto the stack and returns a pointer to
the memory address of that object. For example:
func foo() {
tempvar ptr: MyStruct* = new MyStruct(a=1, b=2);
assert ptr.a = 1;
assert ptr.b = 2;
return ();
}
Note that unlike alloc()
, which allocates a new memory segment, the new
operator
creates the object in the execution segment (see Segments). Since memory in Cairo is never
freed, both approaches have a similar outcome – you can use the pointer even after the function
ends.
On the other hand, this means that the new
operator can’t be used for an arbitrary-sized arrays.
The new
operator is useful since it allows you to allocate the memory and initialize the object
in one instruction. In fact, you can use multiple new
operators in the same line if necessary.
This is theoretically equivalent to the following code:
tempvar obj: MyStruct = MyStruct(a=1, b=2);
tempvar ptr: MyStruct* = &obj;
However, &obj
is currently not supported for tempvar
, so this code does not compile.
You can use new
to allocate a fixed-size array using tuples:
func foo() {
tempvar arr: felt* = new (1, 1, 2, 3, 5);
assert arr[4] = 5;
return ();
}
For arrays of structs you’ll need to explicitly cast the pointer:
func foo() {
tempvar arr: MyStruct* = cast(
new (MyStruct(a=1, b=2), MyStruct(a=3, b=4)), MyStruct*
);
assert arr[1].a = 3;
return ();
}