====== 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).
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 := [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.