LogoChemical Docs
Ctrl+K

Unsafe Memory

As a systems language, Chemical gives you direct control over memory when needed, while offering safer abstractions for everyday tasks.

Pointers and References

References (&)

References are safe, non-null pointers managed by the language.

Pointers (*)

Pointers are raw memory addresses, similar to C pointers. They are unsafe to dereference.

In Chemical, when you use & operator on a value, you take a pointer (not a reference), that's because references are taken implicitly in chemical. If the type is a reference, you just need to pass a l-value.

Taking Addresses

var i = 2

var j = &mut i    // Mutable pointer to i

*j = *j + 1       // Modify through reference

// i is now 3

Double Dereference

var i = 123

var j = &i

var k = &j

**k == 123  // Dereference twice to get original value

Address of Dereference

var i = 234

var k = *&i    // Dereference immediately after taking address

// k == 234

Pointer Notation

var i = 345

var j = &i

var k = &*j    // Address of dereferenced value

// *k == 345

Pointer Arithmetic

Chemical supports standard pointer arithmetic within unsafe blocks. Basic Operations:

var arr = [10, 20, 30, 40, 50]

var ptr = &arr[0]



*ptr       // 10

ptr++      // Move to next element

*ptr       // 20

ptr++

*ptr       // 30

ptr--      // Move back

*ptr       // 20

Pointer Subtraction

Calculate the distance between two pointers:

var arr = [10, 20, 30, 40, 50]

var ptr1 = &arr[0] + 2    // Points to arr[2]

var ptr2 = &arr[0]        // Points to arr[0]

var diff = ptr1 - ptr2    // 2

Pointer Comparison

Compare pointers to determine relative positions:

var arr = [10, 20, 30, 40, 50]

var ptr1 = &arr[0] + 2

var ptr2 = &arr[0]



ptr1 > ptr2   // true

ptr2 < ptr1   // true

ptr1 == ptr2  // false



var ptr3 = &arr[0] + 2

ptr1 == ptr3  // true (same address)

Index Operator on Pointers

Access memory like an array through pointers:

var arr = [10, 20, 30]

var ptr = &arr[0]

ptr[0]   // 10

ptr[1]   // 20

ptr[2]   // 30

Pointer Access After Arithmetic

Access struct members after pointer arithmetic:

struct Point { var a : int; var b : int }



var p = Point { a : 22, b : 33 }

const j = &p

const k = j + 1

const d = k - 1

d.a == 22 && d.b == 33  // true

Dereferencing Function Return Values

Directly dereference and assign to pointers returned from functions:

func ret_ptr(ptr : *mut int) : *mut int {

    return ptr

}



var i = 20

*ret_ptr(&mut i) = 30

// i is now 30

Type Reflection: sizeof and alignof

Use these built-in macros to get memory characteristics of any type. They return a ubigint or u64.

Basic Usage

var size = sizeof(int)    // 4

var align = alignof(long) // 4 or 8 depending on platform

Platform-Specific Sizes

comptime if(def.is64Bit) {

    comptime if(def.windows) {

        sizeof(long) == 4  // Windows 64-bit: long is still 4 bytes

    } else {

        sizeof(long) == 8  // Linux/Mac 64-bit: long is 8 bytes

    }

}

Use in Comptime Functions

comptime func <T> comptime_size_of() : ubigint {

    return sizeof(T)

}



comptime func <T> comptime_align_of() : ubigint {

    return alignof(T)

}



// Works with generics

comptime_size_of<int>()  // 4

Unsafe Blocks

Operations that could potentially crash the program (like manual memory management or pointer dereferencing) must be wrapped in an unsafe block. This serves as a "warning sign" in your code.

unsafe {

    var ptr = malloc(16) as *mut int

    *ptr = 100

    free(ptr)

}

Manual Allocation

Chemical provides keywords for manual memory management within unsafe blocks:

new - Basic Allocation

// Allocate memory for a type

var x = new int

*x = 13

dealloc x



// Works with const too

const x = new int

*x = 13

dealloc x

new - Pointer Types

var x = new *int

var y = 13

*x = &y

const ptr = *x

*ptr == 13

dealloc x

new - With Struct Types

// Allocate without initialization (zero-initialized)

var x = new MyStruct

x.a = 234

x.b = 111



// Allocate with initialization

var x = new MyStruct { a : 10, b : 20 }



// Allocate with constructor call

var x = new Player("Antigravity")

new - Namespaced Types

var x = new namespace::MyStruct

x.a = 821

x.b = 2834

Placement new

Construct an object at a specific memory address without allocating new memory:

// Allocate raw memory

var ptr = malloc(sizeof(MyStruct)) as *mut MyStruct



// Construct at that location

var x = new (ptr) MyStruct { a : 87, b : 33 }



// Use x...

x.a == 87



destruct ptr

Placement new with Constructor

var ptr = malloc(sizeof(Player)) as *mut Player

new (ptr) Player("Alice")

ptr.name == "Alice"

destruct ptr

Placement new Without Variable

var ptr = malloc(sizeof(MyStruct)) as *mut MyStruct

new (ptr) MyStruct { a : 12, b : 43 }

ptr.a == 12  // Access directly through ptr

destruct ptr

Placement new with Variants

variant OptInt {

    Some(value : int)

    None()

}



var ptr = new OptInt

new (ptr) OptInt.Some(763)



var Some(value) = *ptr else return

value == 763



destruct ptr

Deallocation

var x = new int

dealloc x



// For structs with destructors

var p = new Player("Antigravity")

destruct p  // Calls Player.@delete then frees memory



// warning: if you use dealloc with p, destructor won't be called