Wie überprüfe ich, ob ein Zeiger bereits in C freigegeben ist?

Lesezeit: 6 Minuten

Kitchas Benutzer-Avatar
Kita

Ich möchte überprüfen, ob ein Zeiger bereits freigegeben ist oder nicht. Wie mache ich das mit dem Gnu-Compiler-Set?

  • Ich glaube nicht, dass Sie das können (zumindest nicht auf tragbare Weise).

    – NPE

    28. November 2011 um 19:01 Uhr

  • Angenommen dort war eine Möglichkeit, dies zu tun. Nehmen wir auch an, dass ein Zeiger p befreit wurde, und dann ein weiterer Block q zugewiesen wurde, die denselben Platz im Speicher belegten. Was würde isFreed(p) Rückkehr? Wäre das anders als isFreed(q)? Wie könnte es anders sein, wenn p == q?

    – Greg Hewgill

    28. November 2011 um 19:06 Uhr


  • @DavidHeffernan, ich werde mich darum kümmern. Danke für deine Erinnerung.

    – Kita

    28. November 2011 um 19:11 Uhr

Chads Benutzeravatar
Tschad

Du kannst nicht. Der Weg, dies zu verfolgen, wäre, den Zeiger zu zuweisen 0 oder NULL nachdem Sie es befreit haben. Wie Fred Larson jedoch erwähnte, ändert dies nichts an anderen Zeigern, die auf dieselbe Stelle zeigen.

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;

  • Ist es empfehlenswert, Zeigern, die vom System freigegeben werden, Werte zuzuweisen? Was ist, wenn das System sie einem anderen Zeiger zugewiesen hat?

    – Janman

    14. Februar 2014 um 7:42 Uhr

  • Ich glaube, Sie haben die Bedeutung nicht verstanden, dem Zeiger einen NULL-Wert zuzuweisen. Wenn Sie dies tun, bereinigen Sie die im Zeiger gespeicherte Adresse, nicht den Inhalt der im Zeiger gespeicherten Adresse. Dies ist ein bewährtes Verfahren, da es verhindert, dass der bereits freigegebene Zeiger weiter verwendet wird, was Sicherheitsprobleme verursachen kann.

    – Jorge Gabriel Siqueira

    26. Januar 2016 um 18:28 Uhr


Benutzeravatar von cnicutar
Cnicutar

Du kannst nicht. Einfach zuweisen NULL dazu nach dir free es, um sicherzustellen, dass Sie es nicht zweimal freigeben (es ist in Ordnung free(NULL)).

Besser noch, schreiben Sie nach Möglichkeit keinen Code, bei dem Sie “vergessen”, dass Sie ihn bereits freigegeben haben.

BEARBEITEN

Interpretation der Frage als wie man herausfindet, ob der Speicher, auf den ein Zeiger zeigt, bereits freigegeben ist: Du kannst es nicht. Sie müssen Ihre eigene Buchhaltung führen.

  • Natürlich bewirkt die Zuweisung eines Zeigers zu NULL nichts an anderen Zeigern, die auf dieselbe Zuordnung zeigen. Die baumeln noch.

    – Fred Larson

    28. November 2011 um 19:03 Uhr

  • Das geht aber irgendwie an der Frage vorbei. Geben Sie dem OP den Vorteil des Zweifels und interpretieren Sie die Frage als “ob der Speicher, auf den ein Zeiger zeigt, bereits freigegeben ist” (Sie geben keine Zeiger frei, nur Speicher), dann lautet die Frage “Wie kann man feststellen, ob ein bestimmter Zeiger Wert zeigt auf freigegebenen Speicher”.

    – Kerrek SB

    28. November 2011 um 19:03 Uhr

Benutzeravatar von kennytm
kennytm

Es gibt keinen zuverlässigen Weg, um festzustellen, ob ein Zeiger freigegeben wurde, wie Greg kommentierte, der freigegebene Speicher könnte von anderen irrelevanten Daten belegt sein und Sie erhalten ein falsches Ergebnis.

Und tatsächlich gibt es keine Standardmethode, um zu überprüfen, ob ein Zeiger freigegeben ist. Das gesagt, glibc hat Funktionen (mcheck, mprobe), um den Malloc-Status eines Zeigers für zu finden Haufenkonsistenzprüfungund eine davon besteht darin, zu sehen, ob ein Zeiger freigegeben ist.

Jedochwerden diese Funktionen hauptsächlich nur zum Debuggen verwendet und sind nicht Thread-sicher. Wenn Sie sich der Anforderung nicht sicher sind, vermeiden Sie diese Funktionen. Stellen Sie einfach sicher, dass Sie gekoppelt haben malloc/free.


Beispiel http://ideone.com/MDJkj:

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

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}

  • Danke für die Hilfe. Ich möchte dies tun, während ich mit gdb aus einer Kerndatei debugge, leider kann ich keine Funktionen aufrufen! Aber vielleicht kann ich mir die Quelle ansehen und herausfinden, wie mcheck und mprobe funktionieren.

    – Sam Watkins

    21. Februar 2012 um 6:58 Uhr

  • Seltsamerweise bekomme ich a SIGABRT wenn ich es versuche und mprobe den Status einer freigegebenen Variablen, aber nur, wenn ich benutze -lmcheck. Wenn ich es mit einrichte mcheck Ich bekomme kein SIGABRT. Außerhalb meines kleinen Testprogramms kann ich das leider nicht verwenden mcheck() Option, weil Qt irgendwie eine Art Heap-Zuweisung vor sogar der ersten Zeile von main() einzufügen scheint).

    – jrh

    12. Mai 2020 um 14:27 Uhr

Sie können das Konzept der Zuweisung von NULL zum Zeigerwert erweitern, indem Sie ein Makro schreiben, das dies für Sie erledigt. Zum Beispiel:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

Solange Sie sicherstellen, dass Ihr Code nur FREE() und nicht free() verwendet, können Sie ziemlich sicher sein, dass der von Ihnen geschriebene Code nicht zweimal denselben Speicher freigibt. Natürlich trägt das nichts dazu bei, mehrere Aufrufe von Bibliotheksfunktionen zu verhindern, die Speicher freigeben. Und es trägt nicht dazu bei, zu garantieren, dass es für jeden Malloc einen kostenlosen gibt.

Sie können dies mit einer Funktion versuchen, aber es wird umständlich, weil Sie einen Referenzoperator einwerfen müssen und es nicht mehr wie ein normaler Aufruf von free() aussieht.

Du nicht, weil du es nicht kannst.

Verfolgen Sie die Hinweise, die Sie erhalten malloc() und nur diese befreien, und nur einmal.

Wenn Sie so wollen, Speicher hat keinen Speicher, also weiß er nicht, ob er zugewiesen ist oder nicht. Nur der Speichermanager Ihres Betriebssystems kann Ihnen das sagen (aber C enthält keinen standardisierten Mechanismus, um diese Informationen abzufragen).

Benutzeravatar der Community
Gemeinschaft

Ich weiß, dass diese Antwort ist a little bit spät, aber ich habe gerade diese Antwort gelesen und Code geschrieben, um Folgendes zu überprüfen:

Free wird den Speicherblock einfügen eine eigene kostenlose Sperrliste. Normalerweise versucht es auch, benachbarte Blöcke im Adressraum zusammenzufügen. Die freie Sperrliste ist nur eine kreisförmige Liste von Speicherbrocken, die natürlich am Anfang einige Verwaltungsdaten enthalten. Die Freiliste ist auch der erste Standortmalloc sucht bei Bedarf nach einem neuen Speicherblock. Es wird gescannt, bevor es neuen Speicher vom Betriebssystem anfordert. Wenn ein Chunk gefunden wird, der größer ist als der benötigte Speicher, wird er einfach in zwei Teile geteilt. Einer wird an den Anrufer zurückgegeben, der andere wird zurück in die freie Liste gestellt.

Dieser Code prüft nur, ob der erste zugewiesene Zeiger freigegeben ist:

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

Ich habe diesen Code auf HP-UX und Linux Redhat getestet und er funktioniert für den Fall von nur einem Zeiger.

Benutzeravatar von Matt Stead
Matt Stead

Schreiben Sie eine Funktion, um das Signal SIGABRT abzufangen

  • Definitiv nicht. Sie können einen SIGABRT nicht wirklich fangen: stackoverflow.com/questions/8934879/…

    – ocirocir

    3. März 2021 um 18:54 Uhr

1407520cookie-checkWie überprüfe ich, ob ein Zeiger bereits in C freigegeben ist?

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

Privacy policy