37. Dynamische Speicherverwaltung

Grundlagen

Bisher: char text[200]; – aber was, wenn Texte verschiedener Länge bearbeitet werden sollen?

Antwort: Dynamische Speicherverwaltung: Datenstrukturen können zur Laufzeit angelegt werden.

In C geht das “zu Fuß”, jeder Speicherbereich muss eigens reserviert und wieder freigegeben werden.

Tatsächlich sorgt unter Unix das Betriebssystem dafür, dass Speicher und Filehandles (das, was unterhalb von FILEs steht) freigegeben werden, wenn das Programm (der Prozess) terminiert – zumindest für FILEs ist es aber schlechter Stil, sich darauf zu verlassen.

In stdlib.h:

void *malloc(size_t size);
void free(void *ptr);

Malloc reserviert size Bytes und gibt einen Pointer darauf zurück (void* kann jedem Pointer zugewiesen werden), free gibt den Bereich wieder frei. Nach free darf auf den Bereich nicht mehr zugegriffen werden.

Ein einfaches Beispiel:

int *intptr; /* hier zeigt intptr auf nichts --
  ein Zugriff wird mit einem segfault bestraft. */
intptr = malloc(sizeof(int));
/* Jetzt dürfen wir mit *intptr machen, was wir wollen */
*intptr = 3;
printf("%d\n", *intptr);
free(intptr);

Ein etwas sinnvolleres Beispiel:

size_t fsize(FILE *f)
{
  size_t sz, pos=ftell(f);
  fseek(f, 0L, SEEK_END);
  sz = ftell(f);
  fseek(f, pos, SEEK_SET);
  return sz;
}

char *readText(FILE *f, int *len)
{
  char *tx;

  *len = fsize(f);
  if ((tx = malloc(*len*sizeof(char)))) {
    fread(tx, 1, *len, f);
  }
  return tx;
}

Das sizeof(char) im malloc-Ausdruck tut nichts, weil per definitionem sizeof(char)==1. Trotzdem ist es eine gute Idee, sich die Verwendung von sizeof anzugewöhnen. Ein malloc, in dessen Argument kein sizeof steht, ist verdächtig, denn meistens will man eine Anzahl von Objekten allozieren, nicht eine Anzahl von Bytes.

Darüber hinaus sollte das f, das readtext übergeben wird, im Binary Mode geöffnet sein. Unter Unix ist das praktisch immer egal, und DOS/Windows allerdings wird ftell mit nicht-binary geöffneten Dateien hier unter Umständen völligen Unfug zurückgeben. Üblicherweise würde man die Dateigröße eher in betriebssystemabhängiger Weise bestimmen – es gibt keine voll portable Art, das zu machen. Das liegt nicht zuletzt daran, dass die Zahl der Zeichen, die man aus einer Datei lesen kann, z.B. davon abhängen mag, in welchem Modus sie geöffnet ist.

Unter Unix ist die stat-Funktion ein heißer Kandidat für solche Zwecke.

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Schreibt ein Program, das in einer Schleife 106 Mal jeweils 10 Bytes alloziert – insgesamt also 10 MB. Natürlich solltet ihr auch aufhören, wenn malloc NULL zurückgibt. Lasst euer Programm dann auf eine Eingabe warten (z.B. mit fgetc – ihr müsst wahrscheinlich return drücken, damit das Programm die Eingabe auch bekommt). Seht euch an, wie viel Speicher das Programm braucht, während es auf die Eingabe wartet.

Wiederholt das Experiment mit einem Programm, das ein Mal 10 MB am Stück alloziert.

Was beobachtet ihr? Habt ihr eine Erklärung?

Anmerkung: Wie ihr den Speicherbedarf eines Prozesses rausbekommt, ist stark systemabhängig. Unter Linux könnt ihr das Kommando ps u verwenden und in der VSZ-Spalte nachsehen, unter Windows sagt einem das glaube ich der Prozessmanager, den ihr bekommt, wenn ihr ctrl-alt-del (strg-alt-entf) drückt.


Markus Demleitner

Copyright Notice