C – befreiende Strukturen

Lesezeit: 6 Minuten

Nehmen wir an, ich habe diese Struktur

typedef struct person{
    char firstName[100], surName[51]
} PERSON;

und ich weise Raum durch malloc zu und fülle ihn mit einigen Werten

PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");

Was ist der richtige und sichere Weg, um den gesamten von dieser Struktur belegten Speicher freizugeben? Ist “kostenlos (Testperson);” genug oder muss ich das Attribut jeder Struktur einzeln freigeben?

Das führt mich zu einer anderen Frage – wie werden Strukturen im Gedächtnis gespeichert? Ich habe ein seltsames Verhalten bemerkt – wenn ich versuche, die Strukturadresse zu drucken, ist sie gleich der Adresse des ersten Attributs.

printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);

Das bedeutet, dass dieses free(testPerson) gleich diesem free(testPerson->firstName) sein sollte;

und das ist nicht, was ich tun möchte.

Vielen Dank

  • Eine gute Faustregel: Für jeden Malloc braucht man genau einen freien (nicht mehr und nicht weniger).

    – Chris Eberle

    27. November 2012 um 18:40 Uhr

  • Manchmal möchten Sie möglicherweise früher freigeben, und dies erfordert möglicherweise mehr Freizeichen (da einige in bedingten if-Anweisungen enthalten sind) als Malloc-Zeichen

    – Kodierer

    13. Juli um 17:51 Uhr

Benutzeravatar von Omkant
Omkant

Einfache Antwort: free(testPerson) reicht .

Denken Sie daran, dass Sie verwenden können free() nur wenn Sie Speicher mit zugewiesen haben malloc, calloc oder realloc.

In Ihrem Fall haben Sie nur einen Malloced-Speicher für testPerson das ist also ausreichend zu befreien.

Wenn Sie verwendet haben char * firstname , *last surName dann müssen Sie in diesem Fall den Speicher zugewiesen haben, um den Namen zu speichern, und deshalb mussten Sie jedes Mitglied einzeln freigeben.

Hier ist auch ein Punkt, an dem es in umgekehrter Reihenfolge sein sollte; Das bedeutet, dass der Speicher für Elemente später zugewiesen wird free() es gibt dann zuerst den Zeiger auf Objekt frei.

Wenn Sie jedes Element freigeben, können Sie die unten gezeigte Demo sehen:

typedef struct Person
{
char * firstname , *last surName;
}Person;
Person *ptrobj =malloc(sizeof(Person)); // memory allocation for struct
ptrobj->firstname = malloc(n); // memory allocation for firstname
ptrobj->surName = malloc(m); // memory allocation for surName

.
. // do whatever you want

free(ptrobj->surName);
free(ptrobj->firstname);
free(ptrobj);

Der Grund dafür ist, wenn Sie die freigeben ptrobj zuerst, dann gibt es ein Speicherleck, das der Speicher ist, der von zugewiesen wird firstname und suName Zeiger.

  • Beim letzten Satz liegt das Speicherleck wahrscheinlich an der Strukturauffüllung.

    – Schasch

    28. November 2012 um 10:05 Uhr


  • Nein. Ich sagte, dass wenn free(ptrobj) ist dann erledigt firstname und suname Zeiger sind die Mitglieder auf dem Haufen, der weg ist, also der Speicher, der von zugewiesen wurde firstname und suname wird nicht befreit, denn um es zu befreien, müssen Sie schreiben free(firstname) aber vorname existiert nicht mehr ..hopw du hast es

    – Omkant

    28. November 2012 um 10:11 Uhr

Benutzeravatar von Viswesn
Viswestn

Zuerst sollten Sie wissen, wie viel Speicher zugewiesen wird, wenn Sie Speicher im folgenden Fall definieren und zuweisen.

   typedef struct person{
       char firstName[100], surName[51]
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

1) Die Größe von (PERSON) gibt jetzt 151 Bytes zurück (ohne Auffüllen)

2) Der Speicher von 151 Bytes wird im Heap allokiert.

3) Um frei zu werden, rufen Sie kostenlos an (Testperson).

aber wenn Sie Ihre Struktur als deklarieren

  typedef struct person{
      char *firstName, *surName;
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

dann

1) Die Größe von (PERSON) gibt jetzt 8 Bytes zurück (ohne Auffüllen)

2) Sie müssen Speicher für firstName und surName zuweisen, indem Sie malloc() oder calloc() aufrufen. wie

        testPerson->firstName = (char *)malloc(100);

3) Befreien Sie zuerst die Mitglieder in der Struktur, bevor Sie die Struktur befreien. dh free(testPerson->firstName); frei(Testperson->Nachname); kostenlos (Testperson);

  • Vielen Dank. Ich muss mich also nur um die dynamischen Variablen kümmern, wie bei Funktionen

    – Benutzer10099

    27. November 2012 um 19:05 Uhr

Benutzeravatar von S Dao
S Dao

free ist nicht genug, free markiert den Speicher nur als unbenutzt, die Strukturdaten bleiben dort, bis sie überschrieben werden. Stellen Sie den Zeiger sicherheitshalber auf NULL nach free.

Ex:

if (testPerson) {
    free(testPerson);
    testPerson = NULL;
}

struct ist ähnlich wie ein Array, es ist ein Speicherblock. Sie können über seinen Offset auf das Strukturmitglied zugreifen. Das Mitglied der ersten Struktur wird bei Offset platziert 0 Die Adresse des Members der ersten Struktur ist also dieselbe wie die Adresse der Struktur.

Weil Sie das definiert haben struct als bestehend aus char Arrays, die beiden Strings sind die Struktur und die Befreiung der struct ist ausreichend, noch gibt es eine Möglichkeit, die zu befreien struct aber behalten Sie die Arrays. Für diesen Fall würden Sie so etwas tun wollen struct { char *firstName, *lastName; }aber dann müssen Sie Speicher für die Namen separat zuweisen und die Frage behandeln, wann Sie ihn freigeben das Erinnerung.

Nebenbei: Gibt es eine Grund Sie möchten die Namen nach dem beibehalten struct wurde befreit?

Auf diese Weise müssen Sie die Struktur nur freigeben, da die Felder Arrays mit statischen Größen sind, die als Teil der Struktur zugewiesen werden. Dies ist auch der Grund dafür, dass die angezeigten Adressen übereinstimmen: Das Array ist das Erste in dieser Struktur. Wenn Sie die Felder als char * deklariert haben, müssten Sie sie auch manuell mallocieren und freigeben.

Benutzeravatar von djna
djna

Mallocs und Frees müssen gepaart werden.

malloc schnappte sich einen Speicherplatz, der groß genug für Person war.

Wenn Sie freigeben, teilen Sie malloc mit, dass das Stück Speicher, das “hier” beginnt, nicht mehr benötigt wird, es weiß, wie viel es zugewiesen hat, und gibt es frei.

Ob Sie anrufen

 free(testPerson) 

oder

 free(testPerson->firstName)

Alles, was free() tatsächlich erhält, ist eine Adresse, dieselbe Adresse, es kann nicht sagen, welche Sie angerufen haben. Ihr Code ist jedoch viel klarer, wenn Sie free(testPerson) verwenden – er stimmt eindeutig mit malloc überein.

Sie können keine Typen freigeben, die nicht dynamisch zugewiesen wurden. Obwohl Arrays syntaktisch ähnlich sind (int* x = malloc(sizeof(int) * 4) kann genauso verwendet werden int x[4] ruft an free(firstName) würde wahrscheinlich einen Fehler für letzteres verursachen.

Nehmen Sie zum Beispiel diesen Code:

int x;
free(&x);

free() ist eine Funktion, die einen Zeiger aufnimmt. &x ist ein Zeiger. Dieser Code kann kompiliert werden, obwohl er einfach nicht funktioniert.

Wenn wir vorgeben, dass der gesamte Speicher auf die gleiche Weise zugewiesen wird, x wird in der Definition “zugewiesen”, in der zweiten Zeile “freigegeben” und nach dem Ende des Geltungsbereichs wieder “freigegeben”. Sie können dieselbe Ressource nicht zweimal freigeben; es wird Ihnen einen Fehler geben.

Dies erwähnt nicht einmal die Tatsache, dass Sie aus bestimmten Gründen den Speicher unter möglicherweise nicht freigeben können x ohne das Programm zu schließen.

tl; dr: Befreie einfach die struct und es wird dir gut gehen. Nicht Rufen Sie kostenlos auf Arrays an; Rufen Sie es nur auf dynamisch zugewiesenem Speicher auf.

  • Außerdem werden Variablen normalerweise nicht auf dem Heap allokiert, deshalb free(&x) könnte schon scheitern.

    – Nikolas R

    27. November 2012 um 18:49 Uhr

  • Ich bin versucht, für wirklich nachlässigen Sprachgebrauch abzustimmen, aber ich möchte einen neuen Benutzer nicht davon abhalten, etwas zu posten. Es gibt jedoch zwei eklatante Fehler, auf die hingewiesen werden muss: Es ist nicht klar, was Sie mit “Arrays werden durch Zeiger dargestellt” meinen, und es ist nicht klar, was “gültiger Code” bedeutet. Ganzzahl x; kostenlos(&x); ist kein gültiger Code.

    – MK.

    27. November 2012 um 19:01 Uhr

  • @MK.: Vielen Dank für den Hinweis auf diese Fehler; Ich habe versucht herauszufinden, wie man es richtig formuliert, weil ich sicherstellen wollte, dass ich keine Sprache verwende, die für C++ und nicht für C gilt. Es ist jetzt viel klarer.

    – Unbestimmt

    27. November 2012 um 19:16 Uhr


1417160cookie-checkC – befreiende Strukturen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy