wie ‘frei’ funktioniert, wenn der Zeiger inkrementiert wird

Lesezeit: 4 Minuten

Wenn malloc aufgerufen wird, wird die Größe neben dem zugewiesenen Block gespeichert, sodass free weiß, wie viel freizugeben ist usw. ( http://c-faq.com/malloc/freesize.html ).

Meine Frage ist: Angenommen, wir haben Speicher dynamisch zugewiesen und erhöhen später im Code den Zeiger

 pointer++

Und dann später, wenn ich a anrufe

free(pointer) 

welcher Speicher wird tatsächlich freigegeben.

Ist es die Anzahl der zugewiesenen Bytes, beginnend mit der aktuellen Adresse, auf die der „Zeiger“ zeigt, oder mit der Basisadresse, der es zugewiesen wurde.

Benutzer-Avatar
Alexander Geßler

Du musst free() der gleiche Zeiger, den Sie von erhalten haben malloc(). Das Erhöhen, Ändern oder Ändern ist ein undefiniertes Verhalten, das normalerweise ein Segmentierungsfehler ist.

Stellen Sie sich den Zeiger, den Sie erhalten, als ein Buch aus einer Bibliothek vor. Du kommst nach Hause und liest es. Danach entfernen Sie die Titelseite und den Buchrücken und geben es der Bibliothekarin zurück. Wird er es akzeptieren oder bist du jetzt in ernsthaften Schwierigkeiten? 😉

  • “Normalerweise”? Ich begrüße Ihren Optimismus!

    Roger Pate

    11. März 2010 um 16:00 Uhr

  • Sie können leicht eine Kopie des ursprünglichen Zeigers manipulieren, vergessen Sie nur nicht, sich an den ursprünglichen Wert zu erinnern. feine Analogie mit der Bibliothek. zumal malloc in einer Bibliothek ist 🙂

    – Emvee

    11. März 2010 um 16:05 Uhr

  • @havee: IOW, du kann Bewahren Sie ein Lesezeichen im Buch auf und verschieben Sie es nach Bedarf 🙂

    – Tim Schäfer

    11. März 2010 um 18:02 Uhr

  • Wenn ich eine Kopie des von malloc zurückgegebenen Zeigers erstelle und versuche, diese Kopie freizugeben, wird es funktionieren?

    – Benutzer10607

    22. Oktober 2014 um 7:59 Uhr

  • @ user10607 Ja, das wird es!

    – Alexander Geßler

    22. Oktober 2014 um 9:38 Uhr

Sie können nur anrufen free() auf einen Wert, den Sie zuvor erhalten haben malloc(), calloc()oder realloc() (oder NULL). Alles andere ist undefiniert.

Beispielsweise könnte eine Implementierung die Größe des zugewiesenen Blocks in 4 Bytes vor der Rücksendeadresse von speichern malloc(). Dann, free() geht 4 Bytes zurück und ermittelt die Größe. Dies würde nicht funktionieren, wenn Sie den ursprünglichen Zeiger nicht zurück an übergeben free().

Es wird undefiniertes Verhalten verursachen. Höchstwahrscheinlich wird es Ihr Programm entweder sofort oder später zum Absturz bringen.

  • Lesen Sie für weitere Informationen, wie der Heap funktioniert. Die gebräuchlichste Heap-Implementierung ist eine bidirektionale verknüpfte Liste, die ihre Buchhaltungsinformationen zwischen den Blöcken von Benutzerdaten (von malloc zurückgegebene Bereiche) enthält. Die Buchhaltungsdaten bestehen aus Zeigern oder Offsets auf den vorherigen/nächsten Bereich und Statusinformationen, die angeben, ob der Bereich zugewiesen ist oder nicht.

    – Tronik

    11. März 2010 um 15:41 Uhr

  • @Tronic: Oder es könnte zu einer stillen Datenbeschädigung führen, was noch schlimmer ist.

    – David Thornley

    11. März 2010 um 15:47 Uhr

  • @Tronic: Das ist die übliche Implementierung auf Unix-Plattformen. Windows verwendet die RtlHeap-Bibliothek, siehe ( msdn.microsoft.com/en-us/library/ms797604.aspx ), die ganz anders funktioniert.

    – Billy ONeal

    11. März 2010 um 15:55 Uhr

  • @Billy: In diesem Artikel gibt es nichts, was darauf hindeutet, dass es anders funktioniert, und tatsächlich wird nichts konkret darüber gesagt, wie der Heap intern strukturiert ist, außer dass er etwas Platz verbraucht: „Das System verwendet Speicher aus dem privaten Heap, um den Heap zu speichern Support-Strukturen … die Anforderung kann aufgrund von System-Overhead fehlschlagen.”

    Roger Pate

    11. März 2010 um 16:32 Uhr


  • @ Roger Pate: Ich habe nicht gesagt, dass Tronic falsch war. Leider ist die einzige gute Ressource, die ich finden konnte, um detailliert zu beschreiben, wie RtlHeap intern funktioniert, ein Buch in meinem Regal (“Sichere Codierung in C und C++”). EDIT: Und fürs Protokoll, ich habe seine Antwort positiv bewertet;)

    – Billy ONeal

    11. März 2010 um 19:08 Uhr


Das ist undefiniertes Verhalten. Und es wird höchstwahrscheinlich später zu Problemen führen.

Wenn Sie den Zeiger erhöhen, ohne den ursprünglichen mallocierten Ort zu speichern, können Sie ihn nicht frei anrufen. Sie müssen den ursprünglichen Speicherort irgendwo speichern und beim Erhöhen einen temporären Punkt verwenden.

Benutzer-Avatar
Andrej

tun pointer++ zum ursprünglichen Zeiger ist furchtbar falsch. Das Ergebnis der Freigabe kann bei verschiedenen Implementierungen unterschiedlich sein, aber Sie sollten es definitiv nicht tun.

Benutzer-Avatar
sbi

Der Code, der den freien Speicherplatz verwaltet, geht einfach davon aus, dass Sie ihm nicht den falschen Zeiger geben würden. Es nimmt alles, was Sie geben, prüft es nicht auf Plausibilität und interpretiert es so, wie es den rechten Zeiger interpretieren würde. Es wird gemäß den Werten handeln, die es von den Speicherstellen liest, die es betrachtet, vorausgesetzt, dass der Zeiger rechtmäßig erhalten wurde. Wenn Sie ihm einen verirrten Zeiger übergeben, wird er unsinnige Werte finden und sich daher unsinnig verhalten.

Das nennt man undefiniertes Verhalten und es ist eine gemeine Sache. Es kann Ihre Festplatte formatieren, Ihre CPU toasten oder dafür sorgen, dass Ihr Programm scheinbar so funktioniert, wie es erwartet wird, bis Sie in Rente gehen. Man weiß nie.

1312550cookie-checkwie ‘frei’ funktioniert, wenn der Zeiger inkrementiert wird

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

Privacy policy