Frage zu Malloc und Free



  • Achso okay, alles klar.

    Aber jetzt müsste alles stimmten wenn ich es richtig verstanden habe oder?

    void f1(){
      int x = 0;
      int *px;
      int **ppx;
    
      px = &x;
      ppx = &px;
    
      printf("x: %d\t Addr: %p\n", x, &x);
      printf("px: %p\t Addr: %p\n", *px, &px);
      printf("pxx: %p\t Addr: %p\n\n", ppx, &ppx);
    }
    
    void f2(){
      int x = 0;
      int *px = malloc(sizeof(int));
      int **ppx = malloc(sizeof(int *));
    
      *px = x;
      *ppx = &px;
    
      printf("x: %d\t Addr: %p\n", x, &x);
      printf("px: %p\t Addr: %p\n", px, &px);
      printf("pxx: %p\t Addr: %p\n\n", ppx, &ppx);
    
      free(px); 
      free(ppx); 
    }
    


  • Momolo2 schrieb:

    Aber jetzt müsste alles stimmten wenn ich es richtig verstanden habe oder?

    Leider nicht.

    Bei Zeigern/Pointern nimmt man p als Formatspecifier.
    Bei int dann die geünschte Darstellung: o, x, d oder i

    int x = 0;
      int *px;    //  *px  ist ein int.  px ist ein int* (Zeiger auf int)
      int **ppx;  // **ppx ist ein int.  
    
      px = &x;
      ppx = &px;
    
      printf("    x: %d\t Addr: %p\n", x, &x);
      printf("  *px: %d\t   px: %p\t Addr: %p\n", *px, px, &px);
      printf("**pxx: %d\t *ppx: %p\t  ppx: %p\t Addr: %p\n\n", **pc, *ppx, ppx, &ppx);
    }
    

    Stelle den Warnlevel vom Compiler auf Maximum.
    Der kennt die Formatspecifier für printf und gibt enstsprechende Warnungen aus, wenn da was nicht passt.



  • Das hier ist immer noch falsch:

    *px = x;
    *ppx = &px;
    

    px ist ein Zeiger auf int , folglich ist *px ein int , und &px ist ein Zeiger auf einen Zeiger auf int .
    ppx ist ein Zeiger auf einen Zeiger auf int , folglich ist *ppx ein Zeiger auf int .

    Warum also weißt du einen Zeiger auf einen Zeiger auf int ( &px ) einem Zeiger auf int ( *ppx ) zu?



  • Das Problem ist das ich dann den Speicherplatz nicht mehr freigeben kann mit:

    free(px); 
      free(ppx);
    


  • Hallo,

    //Der Pointer px wird im Stack angelegt, zeigt aber auf einen freien int
    //Speicher im Heap indem ein int gespeichert werden kann.
    int *px = malloc(sizeof(int));

    //Der Doppelpointer ppx wird im Stack angelegt, zeigt aber auf einen freien int* Speicher im Heap indem eine weitere Adresse gespeichert ist.
    int **ppx = malloc(sizeof(int *));

    //Du hast die Aufgabe richtig gelöst.
    //So ist es richtig:

    //Der Pointer px zeigt auf eine Adresse im Heap andem ein int gespeichert //werden kann.
    //So bekommt der Speicher im Heap also der Speicher aufdem px zeigt den Wert x //zugewiesen.
    *px = x;

    //Der Doppelpointer px zeigt auf einen Speicher im Heap indem eine Adresse //gespeichert werden kann. Mit der Anweisung, zeigt der Pointer pptx auf einen //Speicher im Heap, indem die Adresse von px gespeichert ist.
    *ppx = &px;

    printf("x: \t%d\t\t Addr: %p\n", x, &x);
    printf("px: \t%p\t Addr: %p\n", px, &px);
    printf("pxx: \t%p\t Addr: %p\n\n", ppx, &ppx);

    free(px);
    free(ppx);

    Also so müsste es aussehen:

    void f(){
    int x = 19;
    int *px = malloc(sizeof(int));
    int **ppx = malloc(sizeof(int *));
    *px = x;
    *ppx = &px;
    //Hier muss die Ausgabe hin
    free(px);
    free(ppx);
    }

    Lg, hoffe ich konnte helfen



  • Momolo3 schrieb:

    Das Problem ist das ich dann den Speicherplatz nicht mehr freigeben kann

    Solange du ppx nicht änderst (nicht verwechseln mit *ppx ), halte ich das für ein Gerücht.

    Und jetzt denkt mal darüber nach, was du *ppx da eigentlich zuweist.

    SebiX0 schrieb:

    //Du hast die Aufgabe richtig gelöst.

    Nein, hat er nicht. Er hat einen Teilaspekt der Aufgabe richtig gelöst.

    SebiX0 schrieb:

    //Der Doppelpointer px zeigt auf einen Speicher im Heap indem eine Adresse //gespeichert werden kann. Mit der Anweisung, zeigt der Pointer pptx auf einen //Speicher im Heap, indem die Adresse von px gespeichert ist.
    *ppx = &px;

    Du hast den Unterschied zwischen px und &px nicht kapiert, und deinen Code nicht mal durch einen vernünftigen Compiler gejagt. Der gibt nämlich völlig zu recht sowas aus:

    Zuweisung von inkompatiblem Zeigertyp
    

    Weil Zeiger auf int inkompatibel ist zu einem Zeiger auf einen Zeiger auf int .

    SebiX0 schrieb:

    Lg, hoffe ich konnte helfen

    Nein, hast du nicht. Mit deinem Beitrag hast du dafür gesorgt, dass Leute, die mehr Ahnung haben als du, deinen Unsinn korrigieren müssen. Das nächste Mal hau deinem Ego auf die Fresse, wenn es dir sagt, dass dein Halbwissen gut genug ist, um einen Beitrag zu schreiben.

    Außerdem fehlende Codetags. Zeigt, dass du den Vorschaubutton komplett ignoriert hast. Toll!



  • Oh man, jets bin ich durcheinander! 😕



  • Wie soll man da durcheinanderkommen? Lass die Codes durch einen vernünftigen Compiler laufen. Schau dir an, welcher davon eine Warnung produziert. So einfach.



  • Die Aufgabenstellung deines Lehrers ist laienhaft und falsch. Sie muss - bei wörtlicher Umsetzung - zu einem Fehler bei free() bzw. einem Speicherleck führen, den du auch schon beobachtet hast:

    > zwei lokale Variablen px und ppx und initialisieren Sie diese mit zwei Adressen, welche Speicher- bereiche auf dem Heap bezeichnen
    das erzwingt, dass jeweils malloc erforderlich ist

    > und den Inhalt der zweiten Variable auf dem Heap mit der Adresse der ersten Variablen auf dem Heap
    hier wird das Überschreiben des oben geforderten ppx-malloc verlangt -> Speicherleck + free()-Fehler (im besten Fall)

    void f(){ 
      int x = 123; 
      int *px; 
      int **ppx; 
    
      px =  malloc(sizeof(int)); 
      /* ppx = malloc(sizeof(int*)); muss raus wegen Nonsens deines Lehrers */
    
      *px = x; /*Initialisieren Sie den Inhalt der ersten Variable auf dem Heap mit dem Wert von x*/
      ppx = &px; /*den Inhalt der zweiten Variable auf dem Heap mit der Adresse der ersten Variablen auf dem Heap*/
    
      printf("x: %d\t Addr: %p\n", x, (void*)&x); 
      printf("px: %p\t Addr: %p\n", (void*)px, (void*)&px); 
      printf("pxx: %p\t Addr: %p\n", (void*)ppx, (void*)&ppx); 
    
      /* free(ppx); muss raus wegen Nonsens deines Lehrers */
      free(px);
    }
    

    http://ideone.com/RutTdA

    Fazit:
    - dein Lehrer hat keine Ahnung
    - du kannst wenig für die Fehler
    - entgegen dieses Beispiels lassen sich Zeiger auch zunächst mal ohne malloc erklären, dein Lehrer versagt auch hierbei, da er das nicht erkannt und in der Aufgabe Zeiger mit malloc verquickt hat



  • Wutz schrieb:

    [...]den Inhalt der zweiten Variable auf dem Heap[...]
    hier wird das Überschreiben des oben geforderten ppx-malloc verlangt -> Speicherleck + free()-Fehler (im besten Fall)

    Blödsinn. Die Formulierung ist unglücklich gewählt, besagt aber dennoch eindeutig, dass hier die Variabel auf dem Heap geändert werden soll - worauf also ppx zeigt, was man auch *ppx nennt. Das "die zweite Variabel auf dem Heap" bezieht sich auf px , welches bereits auf einen int im Heap zeigt; das ist die Erste. Die Zweite ist die, die die Adresse in px halten soll.

    Wutz schrieb:

    - dein Lehrer hat keine Ahnung

    Würde ich pauschal nicht sagen. Vielleicht hat er auch einfach nur Schiss, dass Leute irgendwie nicht kapieren, was Zeiger sind, wenn er nicht explizit klar macht, dass das auch nur Variablen sind. Leute, die z.B. Arrays mit Zeigern verwechseln, gibt es zuauf.

    Oder der Lehrer hat wirklich keine Ahnung.



  • Momolo3 schrieb:

    Das Problem ist das ich dann den Speicherplatz nicht mehr freigeben kann mit:

    free(px); 
      free(ppx);
    

    Kann passieren, wenn beim Umgang mit Zeigern die Adressen von allokiertem Speicher vermurkst werden. Dadurch entstehende Probleme bei der Speicherfreigabe lassen sich aber ganz einfach verhindern (sofern der Code nicht schon vor free() abgestürzt ist):

    void f2 ()
    {
        // die folg. void-Zeiger sollen einzig nur verwendet werden, um die 
        // Adressen des für px und ppx mit malloc() allokierten Speichers zu
        // retten und diesen Speicher später mit free() wieder freizugeben.
        void *px_sav = NULL, *ppx_sav = NULL;
    
        px = malloc(...);
        ppx = malloc(...);
        px_sav = px;
        ppx_sav = ppx;
    
        // vor weiterer Verwendung von px bzw. ppx sollte geprüft werden, ob
        // malloc() überhaupt Speicherplatz allokieren konnte und nicht etwa
        // NULL-Zeiger zurückgegeben hat.
        if (NULL != px) && (NULL != ppx) {
            // ... weitere Verwendung von px und ppx
        }
        // Speicherfreigabe vor Rückkehr der Funktion:
        if (NULL != px_sav) {
            free(px_sav);
            px_sav = NULL;  // kann hier auch entfallen
        }
        if (NULL != ppx_sav) {
            free(ppx_sav);
            ppx_sav = NULL;  // kann hier auch entfallen
        }
        return;
    }
    

Anmelden zum Antworten