βš™οΈ C & C++ Systems Engineering

C 03: Strings, Stack vs. Heap & Manuelle Speicherallokation

Tauche ein in das Speichermanagement: Null-terminierte C-Strings ('\0'), Stack vs. Heap Architektur, malloc(), calloc(), realloc(), free() und die Eliminierung von Memory Leaks.

πŸ”€ 1. C-Strings & das unsichtbare Null-Byte ('\0')

In C gibt es keinen eingebauten string-Datentyp. Ein C-String ist schlicht ein sequentielles Array aus char-Bytes, das zwingend mit dem ASCII-Wert 0 ('\0', Null-Terminator) endet:

char str[] = "C++"; // Belegt im Speicher 4 Bytes: ['C', '+', '+', '\0']
πŸ“ Speicherlayout eines C-Strings:
Index: [ 0 ] [ 1 ] [ 2 ] [ 3 ]
Zeichen: 'C' '+' '+' '\0' <-- Wichtig: Bestimmt das String-Ende!
Hex: 0x43 0x2B 0x2B 0x00
πŸ›‘ Didaktische Analogie: Der GΓΌterzug mit Schlusssignal

Ein C-String gleicht einem Güterzug. Die CPU weiß nicht im Voraus, wie viele Waggons (Buchstaben) angehÀngt sind. Sie fÀhrt von Waggon zu Waggon, bis sie auf das rote Schlusssignal ('\0') stâßt. Fehlt dieses Null-Byte, fÀhrt die CPU ungebremst über fremden Speicher weiter (Buffer Overread)!

🏒 2. Stack vs. Heap: Die Speicherarchitektur

Jedes C-Programm teilt seinen virtuellen Adressraum in klar definierte Segmente auf:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  Hohe Adressen (0x7FFF...)
β”‚ STACK (Automatisch, LIFO, sehr schnell, z.B. 8MB Limit)β”‚  β–Ό wΓ€chst nach unten
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                       (Freier Raum)                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ HEAP (Dynamischer Speicher, manuell mit malloc/free)  β”‚  β–² wΓ€chst nach oben
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ BSS / DATA (Globale & statische Variablen)             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ TEXT SEGMENT (Kompilierter Maschinencode / Read-Only)  β”‚  Niedrige Adressen (0x0000...)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Eigenschaft Stack (Stapelspeicher) Heap (Freispeicher)
Lebensdauer Automatisch an Scope (Funktionsblock {}) gebunden Manuell: Bis free() aufgerufen wird
Grâße Fest zur Compile-Zeit / Begrenzt (Stack Overflow bei riesigen Arrays) Dynamisch zur Laufzeit (GBs an RAM)
Verwaltung CPU Stack Pointer Register (0 Overhead) malloc() / calloc() / realloc() / free()

πŸ› οΈ 3. Dynamische Speicherallokation & Memory Leaks

Der Lebenszyklus einer Heap-Allokation in C:

#include <stdlib.h>

// 1. Speicher auf dem Heap reservieren (z.B. fΓΌr 10 Ganzzahlen):
int* buffer = (int*)malloc(10 * sizeof(int));
if (buffer == NULL) {
    // Allokation fehlgeschlagen (Out of Memory)
    return -1;
}

// 2. Speicher verwenden:
buffer[0] = 123;

// 3. Speicher freigeben & Dangling Pointer eliminieren:
free(buffer);
buffer = NULL; // WICHTIG: Verhindert versehentlichen Zugriff nach Freigabe!

🎯 Aufgaben & Checkliste in aufgabe.c

πŸ’‘ Systems Pro-Tipp: calloc vs. malloc

malloc() reserviert rohen, uninitialisierten Speicher (enthΓ€lt zufΓ€lligen Datensalat/Garbage). calloc(n, size) setzt alle Bits garantiert auf 0!

πŸ’» In Web-IDE ΓΆffnen → ← ZurΓΌck zu C 02 Weiter zu C 04 →