Dynamische Speicherverwaltung
Header:
#include <stdlib.h>
Funktionen:
void *malloc(size_t ElementGröße); // Memory Allocation void *calloc(size_t ElementAnzahl, size_t ElementGröße); // Cleared Memory Allocation void *realloc(void *PointerAufSpeicherBlock, size_t NeueSpeicherBlockGröße); void free(void *PointerAufSpeicherBlock);
- malloc() - Speicher für ein einziges Element zuteilen. Der zugeteilte Speicher wird nicht initialisiert (bekommt einen undefinierten zufälligen Wert).
- calloc() - Speicher für mehrere Elemente auf einmal zuteilen. Der zugeteilte Speicher wird mit 0 initialisiert.
- realloc() - Die Größe des bereits zugeteilten Speicherblocks ändern. Beim Verkleinern wird einfach der "hintere Teil" des Speicherblocks freigegeben, während der "vordere Teil" unverändert bleibt. Beim Vergrößern des Speicherblocks behält der "vordere Teil" seinen Wert, der neue Teil wird einfach "hinten" angehängt. Dieser angehängte Wert ist wie bei malloc() undefiniert.
- free() - gibt den Speicher, der durch malloc()/calloc() zugeteilt wurde, wieder frei.
Auf Performance achten!
Da der Speicher beim "re'alloc'ieren" u.U. auf eine andere Stelle wandert, wird der Inhalt vorher temporär zwischengespeichert und dann automatisch auf die neue Stelle kopiert.
Bei free() folgendes unbedingt beachten:
- Falls ein (nicht mehr benötigter) Speicherbereich nicht freigegeben wird (weil z.B. der Pointer darauf nicht mehr zu ermitteln ist), bleibt er blokiert, bis der Prozess zu Ende ist. Falls die Zuteilung des Speichers mit malloc() in einer Schleife stattfindet, kann ein vergessenes free() schnell zum Swapping und danach zum Speicherüberlauf führen.
- Falls ein Speicherbereich freigegeben wird, der nicht zuvor mit malloc(), calloc() oder realloc() zugeteilt wurde, kann dies katastrophale Folgen haben. Die ganze Speicherverwaltung kann so aus dem Tritt gebracht werden. Daher sollte man darauf achten, daß wirklich nur Speicherplatz freigegeben wird, der auch zugeteilt wurde.
- Speicher, der mit free() freigeben wurde, wird während der Laufzeit des Prozesses nicht wirklich an den Kernel zurückgegeben, sondern in einem so genannten malloc()-Pool gehalten, um bei Bedarf während des laufenden Prozesses wieder darauf zurückgreifen zu können. Erst, wenn der Prozess beendet wurde, geht der Speicher wieder zurück an den Kern.
Ich rate ausdrücklich von der Versuchung ab, Pointer in den int-artigen Variablen (z.B.
unsigned long
) zu speichern! Auf den meisten 32-Bit Systemen entspricht zwar ein Pointer tatsächlich einem unsigned long
. Es wird sogar auf vielen 64-Bit Systemen funktionieren, aber nur solange die Speicherverwaltung Adressen aus dem unteren Adressbereich zurück liefert. Der Fehler kann somit lange Zeit unentdeckt bleiben.
Weitere Infos:
Im Bezug auf Windows siehe den MSDN-Artikel 4-Gigabyte Tuning: BCDEdit and Boot.ini.
(Steuerung von virtual address space
durch den RegistryKey HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference)
Oder auch unter https://tedwvc.wordpress.com/2013/07/16/porting-win32-code-to-64-bit-watch-out-for-pointers/
Zusammenfassung:
Path: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\ Key: AllocationPreference (vom Typ DWORD) Value: 0x100000
Weitere Funktionen:
Header:
// UNIX/Linux #include <stdlib.h> // Windows/MS-DOS #include <malloc.h>
Funktionen:
// Kein Bestandteil von ANSI C, ist aber häufig vorhanden. void *alloca(size_t ElementGröße);
Die Funktion alloca() ist ähnlich der malloc() mit dem Unterschied, daß alloca() den Speicher nicht vom Heap, sondern vom Stack anfordert. Aus diesem Grund muß dieser Speicher nicht explizit mit free() freigegeben werden. Beim Verlassen der Funktion, in der der Speicher zugeteilt wurde, ist der Stack weg - somit der zugeteilte Speicher auch.
Zur Kurzbeschreibung der 64-bit Datenmodelle
Stand: 10.03.2015
— : Jürgen Kreick
EOF