Dynamischer Speicher für Array vs. feste Größe



  • Hallo zusammen,

    ich versuche gerade die dynamische Speicherverwaltung in C zuverstehen. Ein häufiger Anwendungsfall hiervon ist ja zB bei mehrdimensionalen Arrays. Mir ist beispielsweise klar, dass ich in diesem Fall mein Array erweitern kann.

    Angenommen ich will aber mein Array nicht während des Programms erweitern. Ich sehe dann irgendwie nicht so richtig den Sinn der dynamischen Verwaltung.

    Wäre es nicht genauso dynamisch, wenn ich einfach ein Array[i][j] erstelle und i und j einfach vorher individuell bestimme? Beispiel durch Eingabe?
    Dann wird doch auch nur ein entsprechender Speicherbereich gewählt in Abhängigkeit von i und j, oder?



  • So einfach ist das nicht.

    Lokale Variablen werden (meist) auf dem Stack angelegt. Die Größe vom Stack ist begrenzt.
    Lokale Variablen verlieren beim verlassen ihres Scopes ihre Gültigkeit. Der Speicher kann anderweitig benutzt werden.

    Darum sind VLA nicht gerne gesehen. Gerade dann, wenn der Benutzer die Größe bestimmen kann.

    malloc holt den Speicher vom sog. Heap.
    Der ist (viel) größer als der Stack und der Speicher bleibt bis zum free gültig.



  • Dann wäre es doch besser alles dynamisch zu reservieren, oder?
    Gibt es da eine Faustregel, wann man etwas dynamisch gestaltet und nicht?



  • malloc ist teuer (dauert etwas).
    Zur Verwaltung der Speicherbereiche braucht malloc auch Speicher.
    Häufiges malloc und free führt zur Fragmentierung des Speichers.
    Evtl. hängt da noch virtueller Speicher mit drin.
    Bei malloc musst du immer mit Zeigern arbeiten.

    Eine Variable auf dem Stack ist einfach da.
    Die muss nicht extra angelegt werden. Beim Funktionsaufruf wird der Stackpointer entsprechend weiter gesetzt.

    Faustregel: Der Stack darf nicht überlaufen.

    Die Größe hängt vom System (PC, Großrechner, Mikrocontroller) und den Linkeroptionen ab.
    Durch Rekursion bekommst du den Stack auch voll.


  • Mod

    whizzkid23 schrieb:

    Dann wäre es doch besser alles dynamisch zu reservieren, oder?

    Ist langsamer. Und - in C - schwieriger für den Programmierer.

    Gibt es da eine Faustregel, wann man etwas dynamisch gestaltet und nicht?

    Dann und nur dann, wenn es sein muss.



  • Vielleicht kenne ich einfach keinen Anwendungsfall, aber ich kann mir gerade einfach schlecht vorstellen, wann es sich lohnt für ein Array dynamischen Speicher zu verwalten.

    Angenommen ich habe eine Bilddatei als Parameter und möchte die Bildwerte in einem Array speichern. Was wäre jetzt hier angebrachter und warum?
    Mein Ansatz wäre einfach: Größe ermitteln, und ein Array[height][width] erstellen.


  • Mod

    whizzkid23 schrieb:

    Was wäre jetzt hier angebrachter und warum?
    Mein Ansatz wäre einfach: Größe ermitteln, und ein Array[height][width] erstellen.

    Beschreib mal den letzten Schritt im Details.



  • Angenommen ich hab ein Bild im .pgm Format. Da kann ich ja einfach durch die Bildwerte iterieren und zählen, wieviele Werte ich für die Breite und Höhe brauche und mithilfe dieser Infos einfach mein Array anlegen.



  • whizzkid23 schrieb:

    Angenommen ich hab ein Bild im .pgm Format. Da kann ich ja einfach durch die Bildwerte iterieren und zählen, wieviele Werte ich für die Breite und Höhe brauche und mithilfe dieser Infos einfach mein Array anlegen.

    Und wie legst du dieses Array an? 😉



  • Nicht dynamisch?! 😃 Also hätte es einfach fest im Stil von myArray[width][height] erstellt


  • Mod

    whizzkid23 schrieb:

    Nicht dynamisch?! 😃 Also hätte es einfach fest im Stil von myArray[width][height] erstellt

    Du kennst die Größe der Bilder, die dein Programm verarbeiten wird, bereits während du programmierst?



  • Falls du VLA (Variable Length Array) meinst, solltest du wissen, dass diese erst mit dem C-Standard von 1999 eingeführt wurden.
    Davor gab es sie als Option bei manchen Compilern.

    Und mit dem Standard von 2011 müssen sie nicht mehr unterstützt werden.



  • SeppJ schrieb:

    whizzkid23 schrieb:

    Nicht dynamisch?! 😃 Also hätte es einfach fest im Stil von myArray[width][height] erstellt

    Du kennst die Größe der Bilder, die dein Programm verarbeiten wird, bereits während du programmierst?

    Ne, deswegen würd ich es ja "dynamisch" durch die Variablen halten.
    Ich kann ja auch ein Array in Abhängigkeit von Eingaben erstellen. Bspw gibt der Benutzer Zahl x und Zahl y ein. Mit diesem Werten kann doch dann meine Arraygröße bestimme, obwohl ich vorher auch nicht wissen werde, wie groß Array sein wird.



  • Ne, deswegen würd ich es ja "dynamisch" durch die Variablen halten.

    das geht aber nicht - oder du nutzt VLA (was du wohl machst) (https://en.wikipedia.org/wiki/Variable-length_array) welche nicht gern gesehe und erst im aktuellen Standard verfuegbar sind - die haben aber auch eine begrenzte groesse

    ansonsten wird entweder alles was einen Funktionaufruf ueberleben muss kopiert oder auf den Heap gelegt - es gibt keine andere Möglichkeit

    und ueberleg dir einfach mal warum dein Stack im Standardfall nur 1-2MB gross ist dein Heap aber leicht Gigabytes fassen kann - wenn es in den Stack nicht passt muss es in den Heap - daran kann auch deine fehlenden Fantasie nichts aendern



  • Ich drück jetzt mal deutlich aus, was die andren zwei die ganze Zeit andeuten:

    Dinge, die auf dem Stack angelegt werden sollen, müssen ihre Größe zu Compile-Zeit wissen.

    Wenn du also die Größen des Arrays erst zu Laufzeit ermittelst, dann bleibt dir keine andere Wähl als

    A) VLA zu verwenden, wie bereits erwähnt wurde. Ich nehme mal stark an, dass du dies zur Zeit tust, ohne es überhaupt zu bemerken.
    Diese erlauben es dir eben dein array so mit Variablen zu deklarieren, als wären das zur Compile zeit bekannte Konstanten.
    Intern passiert aber was ganz anderes.

    Ich kenn den Usus in C nicht, aber denke die Dinger sind nicht so gerne gesehen - siehe vorherigen Post.

    😎 Eben dynamisch mit malloc anlegen. Daher kommt der Begriff dynamisch ja auch - weil du erst zur Laufzeit entscheiden kannst, wieviel Speicher du haben willst.



  • Aaaah, jetzt macht alles Sinn!
    Vielen Dank für eure Geduld und Erklärungen! 🙂



  • Wenn malloc keinen Speicher mehr findet, gibt es einen Fehlercode, den du prüfen kannst.

    Wenn kein Platz auf dem Stack ist, kannst du das nicht feststellen.

    Bei deinem Beispiel:
    Du kannst dein Programm mit kleinen Bilder testen und es läuft.
    Nimmst du große Bilder stürzt es ab.



  • Was würd man denn dann machen, wenn ich über malloc keinen Speicher mehr anfordern kann?



  • Je nach Programm entweder versuchen mit weniger Speicher auszukommen, anderen vorher angeforderten Speicher freigeben oder im schlimmsten Falle eine Fehlermeldung ausgeben und das Programm beenden. Wobei man per malloc() bei den heutigen Arbeitsspeichergrößen schon wirklich einiges anfordern kann bevor es eng wird.



  • Danke! 🙂


Anmelden zum Antworten