Lyx – Memory Management

Lyx bietet volle Kontrolle über den Speicher. Es nutzt kein automatisches Speichermanagement (kein GC), sondern setzt auf eine Kombination aus Stack-Allokation (automatisch) und Heap-Allokation (manuell).

1) Stack-Allokation (Automatisch)

Der Stack ist der Standard-Speicherort für lokale Variablen. Er ist extrem schnell, da der Speicher beim Funktionsaufruf reserviert und beim Verlassen automatisch freigegeben wird.

Typen auf dem Stack: Primitiven (int, f64, bool), struct und lokale Arrays mit fester Größe.

Gültigkeit: Nur innerhalb der Funktion (Scope), in der sie deklariert wurden.

fn DoWork() {
var x: int64 := 10; // Stack
var point: TPoint;  // Struct auf dem Stack
// Am Ende der Funktion wird der Speicher für x und point sofort frei.
}

2) Heap-Allokation (Manuell)

Daten, die länger existieren müssen oder deren Größe erst zur Laufzeit feststeht, werden auf dem Heap abgelegt.

Typen auf dem Heap: Instanzen von class und dynamische Arrays (array<T>).

Keywords: new reserviert Speicher, dispose gibt ihn frei.

var p := new Player(); // Allokiert auf dem Heap
p.Name := "Lyx-User";
 
// ... Arbeit mit p ...
 
dispose p; // WICHTIG: Manuelle Freigabe, sonst Memory Leak!

3) Dynamische Arrays

Seit v0.2.1 unterstützt Lyx dynamische Arrays als „Fat Pointer“ (Adresse + Länge + Kapazität).

var list: array<int64> := [1, 2, 3]; // Initialisierung auf dem Heap
list.push(4);                        // Vergrößert das Array bei Bedarf
 
PrintInt(list.len());                // Builtin-Funktion für die Länge
 
dispose list;                        // Gibt den gesamten Array-Buffer frei

4) Null-Safety & Safe Navigation

Um „Null Pointer Access“-Abstürze zu minimieren, bietet Lyx moderne Operatoren für Heap-Objekte:

Safe Call (?.): Der Aufruf wird nur ausgeführt, wenn das Objekt nicht null ist.

Null Coalescing (??): Bietet einen Fallback-Wert.

var name := p?.GetName() ?? "Unbekannt";

5) Best Practices für Lyx

Um Speicherfehler zu vermeiden, empfiehlt das Lyx-Team folgende Regeln:

Regel Beschreibung
RAII-Muster Allokiere im Konstruktor (Create), gib frei im Destruktor.
Stack bevorzugen Nutze struct statt class, wenn das Objekt die Funktion nicht verlassen muss.
Dangling Pointers Setze Pointer nach einem dispose auf null, um Double-Frees zu verhindern.
Result-Pattern Nutze std.Result für Operationen, die fehlschlagen könnten, statt null zurückzugeben.

6) Ausblick: Smart Pointers (Roadmap)

Für zukünftige Versionen (v0.6+) ist die Einführung von Smart Pointers geplant, die eine automatisierte Referenzzählung (ARC) ermöglichen, um dispose in vielen Fällen optional zu machen.