Programmierhilfe für Studium gesucht - C



  • Macht es eigentlich einen Unterschied wie ich das Free aufrufe?

    Angenommen es ist so :

    struct Mystring {
    	char *text;
    	size_t len;
    };
    
    void freestr(struct Mystring *del) {
    
    	if (del->text){
    
    	 free(del->text);
    	 del->len = 0;
    	 puts("\nFree\n");
       }
    }
    

    oder

    void freestr(struct Mystring del) {
    
    	if (del.text){   // del ist ja eigentlich nur eine kopie....wobei bei *del auch nur eine Kopie des Zeigers übergeben wird
    // oder habe ich das falsch in Erinnerung?
    
    	 free(del.text);
    	 del.len = 0;
    	 puts("\nFree\n");
       }
    }
    

    In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...



  • Beim Ersten hast du eien Kopie der Adresse und greifst somit auf das Original zu.
    Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.

    unsure schrieb:

    In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...

    Das musst du dann aber auch in deinem freestr sicherstellen.

    In der Aufgabe stand auch etwas von -1


  • Mod

    Ja, das macht einen gewaltigen Unterschied, angesichts der Tatsache, dass du verstehen musst, warum man manchmal Zeiger auf Objekte an Funktionen übergibt und manchmal Kopien der Objekte.

    Nein, es macht im Prinzip keinen Unterschied, da die halbe Funktion bloß Hokuspokus ist. Das mit der Nullprüfung ist 100% sinnlos. Das Nullsetzen schützt dich bloß davor, dass du eventuell in deinem Programm vorhandene Logikfehler beim Testen entdecken könntest. Das was an der Funktion hier wirklich wichtig ist, das free, funktioniert bei beiden Varianten.



  • Das was an der Funktion hier wirklich wichtig ist, das free, funktioniert bei beiden Varianten.

    vs

    Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.

    Ich hätte jetzt auch gedacht das die 2. Variante also mit der Kopie des Objekts nicht "funktioniert"...

    In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...

    Das musst du dann aber auch in deinem freestr sicherstellen.

    if (del->text) macht das doch ? Ok, fehlt der else zweig..

    ...dass du verstehen musst, warum man manchmal Zeiger auf Objekte an Funktionen übergibt und manchmal Kopien der Objekte.

    Das ist mir nicht immer 100% klar... Ne Faustregel gibt´s wohl nicht ?



  • unsure schrieb:

    Das was an der Funktion hier wirklich wichtig ist, das free, funktioniert bei beiden Varianten.

    vs

    Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.

    Ich hätte jetzt auch gedacht das die 2. Variante also mit der Kopie des Objekts nicht "funktioniert"...

    Bei beiden wird der Speicher freigegeben Das wolltest du doch.

    unsure schrieb:

    In beiden Fällen angenommen, der Char Zeiger ist Null wenn kein Speicher alloziert wurde...

    Das musst du dann aber auch in deinem freestr sicherstellen.

    if (del->text) macht das doch ? Ok, fehlt der else zweig..

    Wenn ein NULL-Zeiger ein Anzeichen für nicht allozierten Speicher ist, musst du nach dem freigeben den Zeiger auch auf NULL setzen.

    unsure schrieb:

    ...dass du verstehen musst, warum man manchmal Zeiger auf Objekte an Funktionen übergibt und manchmal Kopien der Objekte.

    Das ist mir nicht immer 100% klar... Ne Faustregel gibt´s wohl nicht ?

    Brauchst du das Original?
    Darfst du es verändern?
    Das hängt auch ein bisschen von der Größe des Objektes ab. Wie teuer ist die Kopieraktion?
    (In den ersten C-Versionen konnte man structs nicht als Ganzes an Funktionen übergeben.)



  • Bei beiden wird der Speicher freigegeben Das wolltest du doch.

    Ja schon, aber natürlich so , das es auch "passt".

    Beim Zweiten änderst du nur die Kopie. Das Original wird nicht verändert, obwohl du den Speicher dafür freigibst -> Crash.

    Aber die Kopie ist ja auch die Kopie der Speicheradresse, also müsste der Speicher für´s Original auch Freigegeben sein? Wann würde das warum crashen?



  • Brauchst du das Original?
    Darfst du es verändern?

    Hm... Ja das kommt jetzt darauf an.. Ich will es auf jedenfall verändern, darum nehme ich normal die Pointer Variante.
    Also ich hätte jetzt so oder so die Pointer Variante (aus dem Bauch heraus) genommen.

    Brauch ich das Original ? Kommt drauf an ob die Freigabe bei der Kopie, siehe obrigen Post , funktioniert..



  • unsure schrieb:

    Ja schon, aber natürlich so , das es auch "passt".

    Wie passt es denn?

    unsure schrieb:

    Aber die Kopie ist ja auch die Kopie der Speicheradresse, also müsste der Speicher für´s Original auch Freigegeben sein?

    Ja

    unsure schrieb:

    Wann würde das warum crashen?

    Das del.len = 0; kommt nicht ins Original zurück.



  • 😮 😮 Merde. Sorry, das hab ich jetzt total übersehen. War / ist n blödes Beispiel.

    Brauch ich das Original

    Meistens schon 🙂 Fast immer. Darum (Bauchgefühl ON) : übergib mal lieber per Reference...


  • Mod

    DirkB schrieb:

    Das del.len = 0; kommt nicht ins Original zurück.

    Die eigentliche Frage ist doch: Wollen wir das überhaupt?

    Lemma: Nutzung eines Objekts nach Zerstörung ist ein Fehler in der Programmlogik.
    Korollar: Bei der Zerstörung des Objekts ist egal, in welchem Zustand es hinterlassen wird.
    Korollar 2: Ein zerstörtes Objekt in einem Zustand zu hinterlassen, bei dem eine Weiterbenutzung keinen Fehler erzeugt, verschleiert eben diese fehlerhafte Weiterbenutzung. Ansonsten würde es nämlich beim Testen abstürzen und man würde den Fehler bemerken.

    In der gleichen Kategorie: Prüfen von Zeigern auf NULL vor free (macht nämlich genau gar nichts, sofern man dann keinen else-Zweig hat, der einen Fehler ausgibt) und setzen von Zeigern auf NULL nach free (verhindert Fehlerfindung beim Testen, dadurch dass man keinen Fehler bei doppeltem free auslöst).



  • In diesem Fall würde ich als das Objekt die struct Mystring sehen.
    Und diese existiert ja noch weiter. Daher sollten die internen Zustände schon eindeutig sein.

    Zudem tritt das Problem mit del.len ja auch beim concat auf.

    Und einen NULL-Pointer zu finden sollte einfacher sein, als einen der sonstwohin zeigt.


Anmelden zum Antworten