free
calls for you.Allocating Memory#
Memory can be allocated on the heap multiple ways.
- Using the
std.mem.malloc<T>(count: Int): &mut T
function. - Using the
new
unary operator.
std.mem.malloc
#
The std.mem.malloc
function is a generic function that allocates memory on the heap. It takes a type parameter T
and an integer count
that specifies how many elements of type T
to allocate.
from std.mem import malloc;
struct Point {
x: Int,
y: Int
}
let p = malloc<Point>(1);
p.x = 5;
p.y = 10;
println(*p);
{x=5, y=10}
new
Unary Operator#
The new
unary operator takes a given value, then moves it to the heap and returns a pointer to it.
struct Point {
x: Int,
y: Int
}
let p: &mut Point = new {x=5, y=10};
p.x = 7;
println(*p);
{x=7, y=10}
Freeing Memory#
All memory is free’d using the builtin free
function. This function takes a pointer to the memory to free.
let p = new {x=5, y=10};
println(*p);
free(p);
Memory Leaks#
Memory leaks occur when memory is allocated on the heap and never free’d. This can lead to a program running out of memory and crashing.
Using the C backend, we can detect memory leaks using valgrind.
main.sg
let p = new {x=5, y=10};
println(*p);
sage -tc main.sg
gcc -o main out.c
valgrind ./main
Output:
{x=5, y=10}
==1158997==
==1158997== HEAP SUMMARY:
==1158997== in use at exit: 272 bytes in 1 blocks
==1158997== total heap usage: 2 allocs, 1 frees, 1,296 bytes allocated
As you can see, there’s a mismatch in the number of allocations and frees, which indicates a memory leak.
Future Work#
Target backends currently have the power to attach garbage collectors or automatic reference counting, but these features are not used in the current backends. Lifetimes plus ownership and borrow checking seem to be the most desirable path forward for Sage.