2012-04-02 10 views
3

Dieser Fehler wird immer ausgelöst, wenn ich versuche, meine zugewiesene Struktur das zweite Mal freizugeben, was es nicht sollte, weil die Struktur auf NULL nach i festgelegt ist Ich befreie es.Fehler: "Zeiger wird freigegeben wurde nicht zugeordnet" in c

hier ist mein struct ohne wirkliche Zeiger im Inneren:

typedef struct{ 
     int frame; 
     double timestamp; 
     int identifier; 
     int state; 
     int unknown1; 
     int unknown2; 
     mtVector normalized; 
     float size; 
     int unknown3; 
     float angle; 
     float majorAxis; 
     float minorAxis; 
     mtVector unknown4; 
     int unknown5[2]; 
     float unknown6; 
    }Touch; 

die Barebone Hauptfunktion:

int main(){ 
    Touch *myTouch = NULL; 
    int inputCounter = 0; 
    //whenever a touch is recognized: 
    ... 
    myTouch = (Touch*)realloc(myTouch,sizeof(Touch)*(inputCounter++)); 
    ... 
    // everything works fine until: 
    freeTouch(myTouch); 
} 

void freeTouch(Touch *f){ 
    if(f != NULL){ 
     free(f); 
     f = NULL; 
    } 
} 

jemand eine Idee?

+0

Dieser Code sollte gut funktionieren.Kannst du einen [minimalen Testfall] (http://sscce.org) schreiben? –

+0

Können Sie zeigen, wie das "zweite Mal" tatsächlich passiert? Der gezeigte Code ruft nur einmal 'freeTouch()' auf. – unwind

Antwort

3

f ist eine lokale Variable. free(f) beeinflusst den zugewiesenen Speicher, aber f = NULL hat keinen Einfluss auf myTouch in freeTouch(myTouch);.

Versuchen

void freeTouch(Touch **f){ 
    if(*f != NULL){ 
     free(*f); 
     *f = NULL; 
    } 
} 

statt und freeTouch(&myTouch) verwenden.

+1

Dies ist wahrscheinlich nicht das Problem, da der enthaltene Code nicht mehrere Aufrufe von 'freeTouch()' zeigt. Auch "frei (NULL)" ist in Ordnung, es hat keinen Sinn, davor zu schützen. – unwind

+0

in meinem ursprünglichen Code myTouch und inputCounter sind Globals, aber mit Ihrem Hinweis habe ich es behoben! void freeTouch() { if (myTouch! = NULL) { frei (myTouch); myTouch = NULL; } } –

+1

@unwind: Ich denke, das OP hatte mehrere Anrufe zu 'freeTouch' irgendwo in seinem '...'. Das Hauptproblem war, dass er in diesem Fall 'myTouch = NULL' nicht gesetzt hat. – Zeta

1

Vor allem nie

x = realloc(x, size); 

verwenden, denn wenn x vor zugeordnet und realloc ausfällt, Sie machen es NULL während der Speicher ist immer noch da und daher erstellen Sie Müll.

Zweitens

void freeTouch(Touch *f); 

erhält einen Zeiger nach Wert und damit den Zeiger selbst nicht ändern kann. So ist Ihre f = NULL; nicht effektiv. Sie müssen Ihren Code ändern:

int main(){ 
    Touch *myTouch = NULL, temp; 
    int inputCounter = 0; 
    //whenever a touch is recognized: 
    ... 
    temp = realloc(myTouch,sizeof(*temp) * (inputCounter++)); 
    if (temp == NULL) 
     /* handle error */ 
    myTouch = temp; 
    ... 
    // everything works fine until: 
    freeTouch(&myTouch); 
} 

void freeTouch(Touch **f){ 
    if(f != NULL && *f != NULL){ 
     free(*f); 
     *f = NULL; 
    } 
} 

Nebenbei bemerkt: Es ist eine gute Idee, realloc (und ebenso malloc) wie folgt zu verwenden:

x = realloc(count * sizeof(*x)); 

Es gibt keine Notwendigkeit besteht, die Ausgabe oder realloc zu werfen. Außerdem können Sie mit sizeof(*x) den Typ x nicht jedes Mal wiederholen.

+2

Übrigens ist es nicht notwendig, '* f! = NULL' zu überprüfen, weil' free (NULL) 'wohldefiniert ist. –

+0

@OliCharlesworth, Sie haben Recht, aber es ist nur eine Angewohnheit von mir – Shahbaz

2

Sie haben zwei Probleme dort. Der erste ist, dass es keine gute Idee ist, den Rückgabewert explizit von malloc oder realloc zu übertragen. Dies kann zu Problemen führen, wenn Sie vergessen, den Prototyp/Header dafür hinzuzufügen.

Zweitens befreit f innerhalb der Funktion die lokale Kopie. Bis C Referenzen erhält, gibt es zwei Möglichkeiten. Zuerst einen Zeiger auf den Zeiger übergeben und verwenden, die:

void freeTouch (Touch **pF){ 
    if (*pF != NULL){ 
     free (*pF); 
     *pF = NULL; 
    } 
} 
: 
freeTouch (&myTouch); 

oder NULL übergeben zurück, so dass Sie zuordnen:

void *freeTouch (Touch *f){ 
    free (f); 
    return NULL; 
} 
: 
myTouch = freeTouch (myTouch); 

Sie werden bemerken, dass der zweite nicht, ob Sie passieren schert in NULL - es ist vollkommen akzeptabel, einen NULL-Zeiger frei zu geben, da es im Grunde ein No-Op ist (außer dem Funktionsaufruf selbst).

Verwandte Themen