"free" führt zu Programmabstürzen



  • ich hab ein eigenes struct.

    ich alloziere speicherplatz:

    MYSTRUCT *test=(MYSTRUCT *)malloc(sizeof(MYSTRUCT));
    if( test == NULL)
    {
        return 1;
    }
    
    free(test); // <-- "Invalid Heap Argument"
    

    wie kann ich das invalide argument zu einem validen argument machen?
    und ich verstehe nich wie vor nicht, was genau jetzt da das problem ist...
    das speicher wird reserviert, kann aber nicht geschlossen werden.


  • Mod

    MFK schrieb:

    Die Ursache ist mit an Sicherheit grenzender Wahrscheinlichkeit ein Bug in deinem Code. Überschreiben von Array-Grenzen ist der häufigste Fehler.

    It0101 schrieb:

    Erstmal wäre es sinnvoll, wenn du deinen Quellcode postest, damit dir überhaupt jemand helfen kann.

    Edit: aber keine 1000 Zeilen, sondern ein Minimalbeispiel bei dem der Fehler noch auftritt.

    DirkB schrieb:

    ratlos! schrieb:

    (ich hab grad keine zeit die genauen fehler rauszusuchen.

    Das System macht die Meldungen nicht zum Spaß. Und wie das bei Computern so üblich ist, ist die genaue Meldung wichtig.

    ratlos! schrieb:

    (auch der compiler meldet beim compilieren keine fehler.

    Auch keine Warnungen? Die musst du auch beachten. Hast du -Wall gesetzt?

    ratlos! schrieb:

    (ich bin ratlos 😕

    Das wirst du auch bleiben, wenn du nicht mehr Informationen raus gibst.

    SeppJ schrieb:

    da der Fehler sich höchstwahrscheinlich an ganz anderer Stelle äußert, als da wo die eigentliche Ursache liegt.

    Das alles gilt immer noch unverändert. Du hast nichts zur Verbesserung der Lage beitragen können. Dir kann man so nicht helfen.

    Der Codefetzen den du zeigst hat mindestens schon einmal einen fehlerhaften, weil unnötigen, Cast drin, der eventuelle Fehler bei der Einbindung von malloc verdeckt. Entferne ihn! Das ist zwar höchstwahrscheinlich nicht der Fehler, aber schließt zumindest eine kleine Möglichkeit aus.



  • p.s.:
    ich hab einige zeilen code eingebaut:

    MYSTRUCT *test=(MYSTRUCT *)malloc(sizeof(MYSTRUCT));
    if( test == NULL)
    {
        return 1;
    }
    
    free(test); // <-- "Invalid Heap Argument"
    
    if( test != NULL)
    {
        printf("ERROR\n");
    }
    

    und so wie es aussieht, wird der speicher tatsächlich nicht geschlossen (es wird "ERROR" ausgegeben).
    was kann ich da machen?


  • Mod

    nachtrag schrieb:

    und so wie es aussieht, wird der speicher tatsächlich nicht geschlossen (es wird "ERROR" ausgegeben).
    was kann ich da machen?

    Wieso sollte da nicht "ERROR" ausgegeben werden? free verändert schließlich sein Argument nicht*.

    *: Und das ist auch gut so! Siehe meinen, Wutz und seldons Rant über NUllpointermissbrauch.



  • SeppJ schrieb:

    Der Codefetzen den du zeigst hat mindestens schon einmal einen fehlerhaften, weil unnötigen, Cast drin, der eventuelle Fehler bei der Einbindung von malloc verdeckt. Entferne ihn! Das ist zwar höchstwahrscheinlich nicht der Fehler, aber schließt zumindest eine kleine Möglichkeit aus.

    ok. sollte man generell nicht einen mit malloc reservierten speicher umcasten?


  • Mod

    ooooook schrieb:

    ok. sollte man generell nicht einen mit malloc reservierten speicher umcasten?

    Man sollte in C generell keinen von malloc und Konsorten zurückgegebenen Pointer umcasten.

    Das gilt natürlich auch für sämtliche andere unnötige Pointercasts. In C sind void* implizit in andere (Daten-)Zeigertypen konvertierbar. Wenn man nun jedoch einen unnötigen Cast einbaut, dann kann der Compiler keine Fehler in der Programmlogik mehr entdecken, zum Beispiel wenn man einen int einem Pointer zuweist*. Die Casts in C sind in ihrem Funktionsumfang sehr mächtig (in C++-Sprech ist ein C-Cast eine Kombination von static-, const- und reinterpret-Cast), man sollte sie sparsam einsetzen und sich ganz genau bewusst sein, was sie tun.

    *: Das wäre hier beispielsweise der Fall, wenn man stdlib.h nicht eingebunden hat. Die Funktion malloc wird dann implizit als int malloc(Argumenttyp); deklariert. Falls sizeof(int) != sizeof(void*) (z.B. 64-Bit System), dann kracht es zur Laufzeit. Das ist auch kein rein theoretischer Fehler, das kam hier im Forum schon öfters vor.

    P.S.: Man sollte erwähnen, dass es durchaus auch Leute gibt, die das anders sehen. Aber deren Argumente haben mir nie eingeleuchtet. Die gefühlte Mehrheit (insbesondere der "Guru"-Programmierer) scheint gegen den Cast zu sein.



  • ich habe jetzt etwas rumprobiert und herausgefunden:
    man sollte an speicher, der schon reserviert wurde, nicht an anderen reservierten speicher hängen.

    z.b.

    char **pointer=malloc(sizeof(char *);
    
    char pointer[0]=malloc(500);
    
    free(pointer[0]);
    free(pointer);
    

    anscheinend löst sowas speicherlecks aus.


  • Mod

    --lösung-- schrieb:

    ich habe jetzt etwas rumprobiert und herausgefunden:
    man sollte an speicher, der schon reserviert wurde, nicht an anderen reservierten speicher hängen.

    z.b.

    char **pointer=malloc(sizeof(char *);
    
    char pointer[0]=malloc(500);
    
    free(pointer[0]);
    free(pointer);
    

    anscheinend löst sowas speicherlecks aus.

    Unsinn. Wenn man den Code mal so weit korrigiert, dass er überhaupt compilierbar ist:

    char **pointer=malloc(sizeof(char *));
    
      pointer[0]=malloc(500);
    
      free(pointer[0]);
      free(pointer);
    

    Dann ist das 1a korrektes, fehlerloses Verhalten.

    Es gilt immer noch:

    MFK schrieb:

    Die Ursache ist mit an Sicherheit grenzender Wahrscheinlichkeit ein Bug in deinem Code. Überschreiben von Array-Grenzen ist der häufigste Fehler.

    It0101 schrieb:

    Erstmal wäre es sinnvoll, wenn du deinen Quellcode postest, damit dir überhaupt jemand helfen kann.

    Edit: aber keine 1000 Zeilen, sondern ein Minimalbeispiel bei dem der Fehler noch auftritt.

    DirkB schrieb:

    ratlos! schrieb:

    (ich hab grad keine zeit die genauen fehler rauszusuchen.

    Das System macht die Meldungen nicht zum Spaß. Und wie das bei Computern so üblich ist, ist die genaue Meldung wichtig.

    ratlos! schrieb:

    (auch der compiler meldet beim compilieren keine fehler.

    Auch keine Warnungen? Die musst du auch beachten. Hast du -Wall gesetzt?

    ratlos! schrieb:

    (ich bin ratlos 😕

    Das wirst du auch bleiben, wenn du nicht mehr Informationen raus gibst.

    SeppJ schrieb:

    da der Fehler sich höchstwahrscheinlich an ganz anderer Stelle äußert, als da wo die eigentliche Ursache liegt.



  • Bitte genau lesen - bei diesem konstrukt das printf, wo man ist und prüfen, warum das Teil NULL ist.
    Wenn ich mal so Probleme habe,
    vor dem free
    if (pointer == NULL) {
    printf("Hier bei -- sollte nicht sein\n");
    }
    else
    free (pointer);

    Das war als Debugging-Hilfe gedacht und nicht als ordentliches Programmdesign.


  • Mod

    Aber wieso sollte der Zeiger jemals Null werden? Hier wurde doch der Heap zerschossen oder ein falscher Pointer ge-free-ed, Nullzeiger kommen nirgends vor.


Anmelden zum Antworten