free()



  • Hallo miteinander,
    für mein Studium muss ich eine Semesterarbeit in C anfertigen. Dabei handelt es sich um einen Simulator, der eine Schreinerei nachbilden soll. Für die Aufträge, Produkte, usw. habe ich Strukturen verwendet. Mittels malloc wird dementsprechend Platz reserviert.
    Nun sollen aber beispielweise (alle) Aufträge wieder gelöscht werden. Mittels free kann ich doch den Speicher wieder frei geben. Das heißt aber anscheinend nicht, dass die Werte gelöscht werden, oder? Weil ich habe folgendes Problem:

    while(p_order_end)
    {
        p_order = p_order_end;
        p_order_end = p_order_end->prev_order;
        free(p_order);
    
        printf("%s",p_order->name);    //Sollte eigtl keinen Wert, bzw error melden. Es kommen aber kryptische Zeichen zurück. Das Feld name ist dabei das erste Element in der Struktur. Verwende ich das Feld nach name, kommt der ehemalige Wert zurück. Es wurde nichts gelöscht.
    }
    

    Meine Erklärung dafür wäre, dass free den Speicherplatz wieder freigibt, aber nicht den Inhalt löscht. Was mich zu der zweiten Frage führt, ob es eine ellegante Möglickeit gäbe, die Werte aller Felder einer Struktur auf 0 zu setzen (dabei handelt es sich um unterschiedliche Datentypen).
    Das wäre in meinem Falle wahrscheinlich nicht unbedingt notwendig, da ich verkettete Listen verwende, und - falls ein einzelner Auftrag gelöscht werden sollte - die Pointer in der Struktur davor, bzw danach angepasst werden würden.
    Es würde mich dennoch interessieren 🙂

    Vielen Dank schon einmal im Vorraus für Eure Hilfe



  • Wenn du Speicher freigegeben hast, dann gehört er nichtmehr dir, d.h. es hat dich nichtmehr zu interessieren was dort dann noch drinnensteht, das könnte alles mögliche sein. Jeder Zugriff drauf ist undefiniert, d.h. was passiert garantiert dir niemand, das Spektrum reicht von gar nichts bis zur Apokalypse.
    Normalerweise wird es natürlich so sein dass direkt nach dem free() dort einfach immer noch die Werte stehen die du hingeschrieben hast, weil der Speicher inzwischen eben kaum schon anders verwendet wird. Wenn du Pech hast, hat aber z.B. das OS die Pages schon freigegeben und dein Programm crashed.
    Freigeben heißt eben, dass es danach nichtmehr dir gehört, also Finger weg davon, selbst ein printf() ist zuviel.
    Warum du den freigegebenen Speicher danach auf 0 setzen willst, ist mir nicht ganz klar.

    Wenn du dein Auto verkaufst kannst du ja auch nichtmehr einfach weiter damit fahren 😉



  • Du bekommst den Speicher doch auch so wie er ist. Bei malloc wird vorher auch nichts gelöscht.
    Ist eine Sache der Performance.
    Wenn du die Daten gelöscht haben willst, mach es selber (vor dem free).
    So ist halt C.

    dot schrieb:

    Warum du den freigegebenen Speicher danach auf 0 setzen willst, ist mir nicht ganz klar.

    Wenn du dein Auto verkaufst kannst du ja auch nichtmehr einfach weiter damit fahren 😉

    Du räumst doch aber auch vorher deine persönlichen Sachen raus.



  • DirkB schrieb:

    Du räumst doch aber auch vorher deine persönlichen Sachen raus.

    Schließlich wirst Du kaum beim neuen Eigentümer Gehör finden, wenn Du ankommst und sagst, Du möchtest gern den Innenraum seines Wagens durchsuchen.



  • Ok danke. Ich glaub ich hab mir da einfach zu viele Gedanken gemacht.
    Klingt logisch, dass mittels free der Speicher nur wieder freigegeben wird. Hätte weiter wohl auch keinen Sinn ^^

    Danke 🙂



  • Deine zweit Frage habe ich vorhin glatt überlesen:

    fabarazzi schrieb:

    ob es eine ellegante Möglickeit gäbe, die Werte aller Felder einer Struktur auf 0 zu setzen (dabei handelt es sich um unterschiedliche Datentypen).

    Du kannst dafür memset nehmen.



  • sag mal du hast nicht zufällig bei Prof. Geiler^^



  • DirkB schrieb:

    Du kannst dafür memset nehmen.

    Danke .. da hätte ich eigtl auch selber draufkommen können ^^

    Prof. Geiler? Nein 😛

    Damit ich nicht noch ein neues Thema eröffnen muss: Ich hab ein Problem mit float Parametern in Funktionen. Alle float-Parameter die ich einer Funktion übergebe, werden falsch interpretiert. Bei double-Werten ist dies aber nicht der Fall. Dazu ein Beispiel:

    void f_step(float f_value)
    {
         printf("%f",f_value);  //Falls ich f_step(1.0f) aufrufe bekomme ich hier eine 0.00000000 Ausgabe. Wieso?
    }
    

  • Mod

    PrettyC schrieb:

    DirkB schrieb:

    Du räumst doch aber auch vorher deine persönlichen Sachen raus.

    Schließlich wirst Du kaum beim neuen Eigentümer Gehör finden, wenn Du ankommst und sagst, Du möchtest gern den Innenraum seines Wagens durchsuchen.

    Eine passendere Analogie wäre, dass man den Wagen in der Garage geparkt hat und ausgestiegen ist. Wenn der Wagen verkauft wird (Speicher wird vom OS zurück genommen und von diesem an andere Prozesse gegeben), wird bei jedem halbwegs normalen OS der Speicher vorher genullt (wäre sonst viel zu unsicher!). Das macht aber schon das OS für dich und das kann das auch extrem effizient, weil es ganze Speicherseiten verwaltet und die kann man in einem Rutsch komplett nullen.

    Wenn du selber noch was im Wagen vorfindest, dann war das ein Familienmitglied (dein eigenes Programm), welches da vorher was reingeschrieben hat und der Speicher war zwischendurch nicht beim OS.


  • Mod

    fabarazzi schrieb:

    Damit ich nicht noch ein neues Thema eröffnen muss: Ich hab ein Problem mit float Parametern in Funktionen. Alle float-Parameter die ich einer Funktion übergebe, werden falsch interpretiert. Bei double-Werten ist dies aber nicht der Fall. Dazu ein Beispiel:

    void f_step(float f_value)
    {
         printf("%f",f_value);  //Falls ich f_step(1.0f) aufrufe bekomme ich hier eine 0.00000000 Ausgabe. Wieso?
    }
    

    Zeig mal ein vollständiges Beispiel, welches den Fehler produziert. Denn:
    http://ideone.com/Em4JL



  • Das ist in der einen c-Datei:

    err = f_steps(p_step,1,get_time);
    

    Und folgendes in einer anderen

    int f_steps(STEP *p_step, int quantity, float time)                //!! ? void?
    {
        [..]
         printf("Kein Fehler %f",time);
        [..]
    }
    

    Deklariert ist die Funktion auch richtig, in der entsprechenden .h-Datei


  • Mod

    SeppJ schrieb:

    Zeig mal ein vollständiges Beispiel, welches den Fehler produziert.



  • work.c

    //Status 
                 err = f_steps(p_step,1,1.0f);
                 if(!err)
                 {
                       /*Neuer Status = alter STATUS + Zeit*/
                       p_order->status += p_step->time; // ODER new_state
    
                       time_verbrauch += p_step->time;
                 }
    

    f_steps.c

    int f_steps(STEP *p_step, int quantity, float time)                
    {
        /*ABHAENGIG VON ZEIT*/
    
        int i = 0;
        int err = 0;
        /*Suche in Arbeitsschritt, welche Ressource verarbeitet wird*/
        if(!p_step->p_ressources && strcmp(p_step->ressource,"")) /*Falls kein Pointer vorhanden, aber Wert existiert*/
        {
            p_ressource = search_ressource(p_step->ressource);
        }
        else
        {
            p_ressource = p_step->p_ressources;
        }
    
        /*Ressource in p_ressource abgelegt (sofern es eine gibt)*/
    
        /*Geld fuer AS vorhanden?*/
        if(kapital<(quantity*time*p_step->price))
        {
            err = 1;
        }
    
        /*Genuegend Ressourcen im Lager vorhanden?*/
        if(p_ressource && p_ressource->stock < (quantity*time))
        {
            err = 2;
        }
    
        /*Ressourcen vom Lagerbestand abziehen, Kapital abzueglich der AS-Kosten*/
        if(!err)
        {
    
            printf("Kein Fehler %f %f",time,p_step->price);
    
            kapital = kapital - time*p_step->price;
            if(p_ressource) p_ressource->stock = p_ressource->stock - (quantity*time);              //!Es sollten eigtl keine 0.x Mengen abgeubcht werden koennen
        }
    
        return err;
    }
    

    Vl sollte ich noch anmerken, dass die Ausgabe in Zeile 35 eigtl "Kein Fehler 1.000000" usw. ausgeben sollte. Heraus kommt aber "Kein Fehler 0.000000" usw.


  • Mod

    Wenn du keine Hilfe möchtest, dann frag doch gar nicht erst.



  • Ein vollständiges Beispiel ist ein minimales compilierbares Programm, bei dem der Fehler auftritt.
    Dazu noch ein paar Infos zu Compiler und Betriebssystem.
    Ansonsten: http://www.c-plusplus.net/forum/136013



  • Ich denke da wurde gerade etwas falsch verstanden. Also ich komme bei diesem Problem gerade einfach nicht weiter und habe keine Idee, wieso genau dieses Problem besteht. Ich versuche es noch einmal detailiert zu erklären und schneide die wichtigen Codeteile heraus:

    Im Grunde genommen möchte ich nur eine Funktion aufrufen, die über Parameter gesteuert wird. Diese Parameter sind ein Pointer, ein Integer und ein Float. Jetzt rufe ich diese Funktion auf und die Parameter werden auch erkannt und verarbeitet. Nur für den Float-Parameter bekomme ich eine falsche Zahl als Rückgabewert. Gebe ich beim Aufruf der Funktion 1.0f als Parameter an, bekomme ich 0.000000 beim Aufruf in der Funktion als Wert zurück. Rufe ich das Ganze mit beispielsweise 1.838 auf, erhalte ich eine riesengroße Zahl als Rückgabewert.

    Baue ich die Funktion um, so dass ich statt des Float-Parameters einen Double-Parameter habe, funktioniert alles wunderbar. Allerdings würde ich gerne wissen, wieso das mit Float nicht funktioniert. Dieses Problem hatte ich an anderer Stelle nämlich auch schon.

    Hier schildere ich es nochmal:

    #include <stdio.h>
    #include <stdlib.h>
    int f_steps(int *p_step, int quantity, float time)
    {
        printf("Wert fuer time: %f",time);
        int err = 0;
    
        //[..] err wird Integer Wert zugewiesen
    
       return err;
    }
    
    //Das Gleiche mit double
    int f_steps2(int *p_step, int quantity, double time)
    {
        printf("Wert fuer time: %lf",time);
        int err = 0;
    
        //[..] err wird Integer Wert zugewiesen
    
       return err;
    }
    
    void main()
    {
       int err,err2;
       int *p_step = 0;
    
       err = f_steps(p_step,1,1.0f);  //Als Ausgabe erfolgt "Wert fuer time: 0.000000"
    
       err2 = f_steps2(p_step,1,1);  //Als Ausgabe erfolgt "Wert fuer time: 1.000000" 
    
       exit(0);
    }
    

    Compiled wird unter Windows mit GNU GCC Compiler
    Editor: Code::Blocks 10.05

    Das Komische daran ist, mit dem online-Compiler (http://ideone.com/ZvI1C) funktioniert das auch wunderbar. Aber wieso funktioniert dann das Ganze bei mir nicht? Kann es sein, dass mein Compiler irgendwelche Probleme bzw Sonderheiten beim Umgang mit Float-Werten hat?



  • Wenn ich in Zeile 16 das %lf in %f ändere, bekomme ich zweimal Wert fuer "time: 1.000000"
    (auch Code:Blocks 10.05 mit dem dazu gelieferten GCC, Windows 7 Home)

    Warum muss es float sein?
    Warum das f hinter der 1.0?

    Bei deinem Original bekomme ich bei f_steps2 die 0.000000. Kann an dem %lf liegen.


  • Mod

    Ist das wirklich 1:1 das Programm, welches den Fehler zeigt? Komplett mal neues Projekt angelegt, diesen Code genommen, komplett neu compiliert und dann kommt diese Ausgabe?

    (Der Formatspezifizierer %lf bei f_steps2 zeugt übrigens nicht von Verständnis von printf. Er ist zwar technisch nicht direkt falsch, aber es ist nicht das was du denkst)



  • Ich habe diese Zeilen eben rauskopiert und als neues Projekt angelegt. Dabei tritt der Fehler nicht auf... Komisch.

    Zu der Frage wieso 1.0f: Eigtl steht dort eine Variable die einen float-Wert beinhaltet. 1.0f habe ich nur testweise hingeschrieben, um den Fehler zu finden.

    Statt dem %lf sollte ich wohl eher %e nehmen. Ist nur hängengeblieben von den anderen Versuchen.

    Also den Code, den ich gerade gepostet habe, da spielt sich alles ab, was die Variablen und die Funktion betrifft:
    In der Funktion f_steps habe ich testweise direkt als ersten Befehl die Ausgabe von time gefordert.
    Und beim Funktionsaufruf (err = f_steps(p_step,1,1.0f)) kann ja an der Variablen auch nichts mehr geändert werden.

    Aber logischerweise muss der Wert von time ja irgendwo verändert werden, aber wo sollte das geschehen? Und wieso funktioniert der Code, wenn ich anstelle des floats ein double, und den Parameter als double übergebe? Und printf natürlich anpasse..


  • Mod

    fabarazzi schrieb:

    Statt dem %lf sollte ich wohl eher %e nehmen. Ist nur hängengeblieben von den anderen Versuchen.

    Erklär mal, was gegen %f spricht. Und ich nehme schonmal vorweg: Deine Erklärung ist falsch.

    Aber logischerweise muss der Wert von time ja irgendwo verändert werden, aber wo sollte das geschehen? Und wieso funktioniert der Code, wenn ich anstelle des floats ein double, und den Parameter als double übergebe? Und printf natürlich anpasse..

    Du wirst irgendwo in dem Teil den du uns verschwiegen hast undefiniertes Verhalten erzeugen. Das ist eben komisch. Und deswegen wurdest du auch schon zigmal aufgefordert:

    SeppJ schrieb:

    Zeig mal ein vollständiges Beispiel, welches den Fehler produziert.

    Aber mir ist das langsam zu blöd. Wenn du nicht geholfen werden möchtest, dann musst du dir eben selber behilflich sein.


Anmelden zum Antworten