Ich möchte überprüfen, ob ein Zeiger bereits freigegeben ist oder nicht. Wie mache ich das mit dem Gnu-Compiler-Set?
Wie überprüfe ich, ob ein Zeiger bereits in C freigegeben ist?
Kita
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
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
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 undmprobe
den Status einer freigegebenen Variablen, aber nur, wenn ich benutze-lmcheck
. Wenn ich es mit einrichtemcheck
Ich bekomme kein SIGABRT. Außerhalb meines kleinen Testprogramms kann ich das leider nicht verwendenmcheck()
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).
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.
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
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 Blockq
zugewiesen wurde, die denselben Platz im Speicher belegten. Was würdeisFreed(p)
Rückkehr? Wäre das anders alsisFreed(q)
? Wie könnte es anders sein, wennp == 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