2013-03-03 9 views
5

Ich bin verwirrt mit dem Einsatz von free() in Bezug auf den Datenstrukturen in C.von malloc und free Verhalten verwirrt

Wenn ich die folgenden Datenstruktur:

struct Person { 
    char *name; 
    int age; 
    float weight; 
    float height; 
}; 

ich für die Speicher am Zuteilen Struktur über malloc() ebenfalls: struct Person *me = malloc(sizeof(struct Person));

Nachdem ich meine Struktur mit der Verwendung fertig bin (rechts vor dem beenden des Programms), ich gehe zugewiesen um den Speicher zu befreien, wie folgt aus:

free(person_pointer->name); 
free(person_pointer); 

die Speicher Befreit, dass die name Zeiger auf mein Wissen notwendig sind, denn wenn ich nur frei person_pointerich nur den Speicher frei, die die Datenstruktur und ihre Mitgliederaber nicht der Speicher zum Speichern zugewiesen wurden Darauf verweisen Zeiger - Mitglieder der Struktur.

Allerdings scheint mit meiner Implementierung valgrind darauf hinzuweisen, dass die erste free() ungültig ist.

Also meine Frage läuft auf: Wenn ich den Speicher freigeben, den eine Struktur über einen Zeiger einnimmt, sollte ich präventiv den Speicher freigeben, auf den Mitgliedszeiger zeigen oder nicht?

EDIT: Das ist mein ganzer Code:

#include <stdio.h> 
#include <stdlib.h> 

struct Person { 
    char *name; 
    int age; 
    float weight; 
    float height; 
}; 

int main(int argc, char **argv) 
{ 
    struct Person *me = malloc(sizeof(struct Person)); 
    me->name = "Fotis"; 
    me->age = 20; 
    me->height = 1.75; 
    me->weight = 75; 

    printf("My name is %s and I am %d years old.\n", me->name, me->age); 
    printf("I am %f meters tall and I weight %f kgs\n", me->height, me->weight); 

    free(me->name); 
    free(me); 

    return 0; 
} 
+0

@Mat mache ich malloc(). Ich werde die Frage bearbeiten, um dies zu klären. – NlightNFotis

+0

@Mat Nur die Frage mit meiner Zuweisungsmethode aktualisiert. Wenn du mehr Informationen brauchst, könnte ich meinen ganzen Code posten, es ist ein ziemlich kleines Programm, aber von jetzt an werde ich es aus Gründen der Klarheit unterlassen. – NlightNFotis

+1

+1 für einen vollständigen Testfall mit Valgrind usw. –

Antwort

5
me->name = "Fotis"; 

/* ... */ 

free(me->name); 

Die Regel lautet:

1 malloc = 1 free 

Sie nicht malloc auf me->name verwendet haben, so dass Sie nicht haben free es.

BTW, me->name sollte von const char * Typ sein.

1

Wenn Sie das tun

me->name = "Fotis"; 

Der name Zeiger nicht von malloc alloced wird, verweist er auf einen Stapel Variable, die in der Strings Tabelle Ihrer Binärdatei bei der Kompilierung gespeichert, daher kann man nicht frei es.

Die Faustregel lautet: Nur frei, was Sie malloced haben.

Sie können diese schreibgeschützte Zeichenfolge jedoch nicht aktualisieren.

Wenn ja so etwas wie:

me->name = strdup("Fotis"); 

Da strdup eine malloc tut (siehe Handbuch), haben Sie es zu befreien, und Sie können die Zeichenfolge nach seiner Erstellung aktualisieren.

1

Ja, Sie müssen den gesamten Speicher von Zeigern innerhalb der Struktur freigeben, wenn Sie sie zugewiesen haben.

Stellen Sie außerdem sicher, dass Sie die Mitglieder freigeben, bevor Sie die Struktur freigeben.

Eine einfache Art sich zu erinnern ist, sie in der umgekehrten Reihenfolge freizugeben, in der Sie zugewiesen haben.

1

Das Problem ist, dass Sie nicht wirklich den Char * Namen in Ihrer Struktur malloc'ed.

struct Person *me = malloc(sizeof(struct Person)); 
me->name = strdup("Fotis"); 
... 
free(me->name); 
free(me); 
return (0); 

Wenn Sie schreiben diese

me->name = "Fotis"; 

Sie eigentlich gar nicht malloc, der Zeiger Name weist auf einen Stapel Variable vom Typ const char *, wich nicht malloc'ed.

+3

'strdup 'ist keine Standardbibliotheksfunktion. Wahrscheinlich am besten nicht zu empfehlen ... –

+0

Das String-Literal wird statisch gespeichert, nicht auf dem Stack. Ein Zeiger darauf wäre in jeder Funktion irgendwo im Programm gültig. – teppic