Pointer

Store an address to any type, allowing you to allocate, load and modify single instances or arrays of the type on the heap

Import

from Pointer import Pointer

from Memory import memset_zero
from String import String

Initialization

Create a struct and use that as the type for the pointer

struct Coord:
    var x: UInt8 
    var y: UInt8
var p1 = Pointer[Coord].alloc(2)
var p2 = Pointer[Coord].alloc(2)

All the values will be garbage, we need to manually zero them if there is a chance we might read the value before writing it, otherwise it'll be undefined behaviour (UB):

memset_zero(p1, 2)
memset_zero(p2, 2)

Operators

Perform operations with the two pointers

if p1:
    print("p1 is not null")
print("p1 and p2 are equal:", p1 == p2)
print("p1 and p2 are not equal:", p1 != p2)
p1 is not null
p1 and p2 are equal: False
p1 and p2 are not equal: True

Register Passable

Let's try printing the zeroed value from the first point:

let coord = p1[0]
print(coord.x)
error: Expression [6]:17:19: invalid call to '__getitem__': result cannot bind generic !mlirtype to memory-only type 'Coord'
    let coord = p1[0]
                ~~^~~

/.modular/Kernels/mojo/Stdlib/Pointer.mojo:118:5: function declared here
    fn __getitem__(self, offset: Int) -> type:
    ^

Take note of the above error, a memory-only type means it can't be passed through registers, we need that behavior to use the [x] syntax on a Pointer. Lets redefine it with @register_passable annotated:

@register_passable
struct Coord:
    var x: UInt8 
    var y: UInt8

Now we'll be able to use Python syntax to access objects of type Coord:

var p1 = Pointer[Coord].alloc(2)
memset_zero(p1, 2)

var coord = p1[0]
print(coord.x)
0

Storing Values

Let's try setting the values

coord.x = 5
coord.y = 5
print(coord.x)
5
print(p1[0].x)
0

Note above that coord is an identifier to memory on the stack or in a register, when we try and print p1[0] it hasn't been modified. We need to write the data.

p1.store(0, coord)
print(p1[0].x)
5

Lets add 5 to it and store it at offset 1

coord.x += 5
coord.y += 5

p1.store(1, coord)

Now print both the coords:

for i in range(2):
    print(p1[i].x)
    print(p1[i].y)
5
5
10
10

Undefined Behaviour

Now we'll destroy the universe by going outside the bounds we allocated:

let third_coord = p1.load(2)
print(third_coord.x)
print(third_coord.y)
179
85

These are garbage values, we've done something very dangerous that will cause undefined behaviour, and allow attackers to access data they shouldn't.

Let's keep going down this dangerous path:

p1 += 2

Now the pointer is pointer is pointing straight to unallocated garbage data! Let's have a look:

for i in range(2):
    print(p1[i].x)
    print(p1[i].y)
179
85
0
0

Oh no! Let's move back to where we were and free the memory, if we forget to free the memory that'll cause a memory leak if this code runs a lot:

p1 -= 2
p1.free()

Build your own struct

It's easy to make mistakes when playing with pointers, let's create a struct to reduce the surface area of potential errors.

struct Coords:
    var data: Pointer[Coord]
    var length: Int

    fn __init__(inout self, length: Int) raises:
        self.data = Pointer[Coord].alloc(length)
        memset_zero(self.data, length)
        self.length = length

    fn __getitem__(self, index: Int) raises -> Coord:
        if index > self.length - 1:
            raise Error("Trying to access index out of bounds")
        return self.data.load(index)

    # This is what will run when the object goes out of scope
    fn __del__(owned self):
        return self.data.free()

We've added some initial safety, this is the bare minimum but instead of allowing potential undefined behaviour, we're causing the program to throw an error when accessing an index out of bounds:

let coords = Coords(5)

print(coords[5].x)
Error: Trying to access index out of bounds

Experiment with your own safety checks and adding functions utilizing the pointer safely, Mojo gives you the power to do whatever you want with pointers, but always remember what uncle ben saidopen in new window