Ich habe dem Zeiger / Zeichenpuffer zwei Bytes Speicher zugewiesen, aber wenn ich ihm "Hallo" zuweise, druckt es immer noch, ohne mir irgendwelche Fehler zu geben. Warum gibt der Compiler mir nicht einen Fehler, der mir sagt, dass nicht genug Speicher zugeteilt wird? Ich lese ein paar Fragen, die fragen, wie man überprüft, wieviel Speicher malloc
tatsächlich zuweist, aber ich habe keine konkrete Antwort gefunden. Sollte die Funktion free
nicht genau wissen, wieviel Speicher buffer
zugeordnet ist?
Der Compiler weiß es nicht. Das ist die Freude und der Schrecken von C. malloc
gehört zur Laufzeit. Alle Compiler wissen, dass Sie es gesagt haben, dass es eine void * zurückgibt, es hat keine Ahnung, wie viel oder wie viel strcpy
wird kopieren.
Tools wie Valgrind erkennen einige dieser Fehler. Andere Programmiersprachen erschweren es, sich in den Fuß zu schießen. Nicht C.
Keine Produktion malloc()
Implementierung sollte verhindern, dass Sie versuchen, über das, was Sie zugewiesen haben, zu schreiben. Es wird angenommen, dass wenn Sie 123 Bytes zuweisen, Sie alles oder weniger als das verwenden, was Sie zugewiesen haben. malloc()
muss aus Effizienzgründen davon ausgehen, dass ein Programmierer seine Zeiger verfolgen wird.
Wenn Sie Speicher verwenden, den Sie nicht explizit und erfolgreich mit malloc()
angegeben haben, erhalten Sie ein nicht definiertes Verhalten. Möglicherweise haben Sie nach n Bytes gefragt, aber Sie haben n + x erhalten, da die malloc()
-Implementierung für die Byteausrichtung optimiert wurde. Oder Sie könnten in ein schwarzes Loch schreiben. Du kannst es nie wissen, deshalb ist es undefiniertes Verhalten.
Das sagte ...
Es gibt malloc()
Implementierungen, die Ihnen Statistiken und Debugging zur Verfügung stellen Diese müssen anstelle der standardmäßigen malloc()
-Funktion verwendet werden, genau wie wenn Sie einen Müll sammeln würden Vielfalt .
Ich habe auch Varianten gesehen, die ausschließlich für LD_PRELOAD entworfen wurden und eine Funktion offenlegen, die es erlaubt, einen Callback mit mindestens einem void pointer als Argument zu definieren. Dieses Argument erwartet eine Struktur, die die statistischen Daten enthält. Andere Tools wie Elektrozaun werden Ihr Programm einfach auf die genaue Anweisung anhalten, die zu einem Überlauf oder Zugriff auf ungültige Blöcke geführt hat. Wie @R .. in Kommentaren hervorhebt, ist das großartig zum Debuggen, aber furchtbar ineffizient.
Ganz ehrlich oder (wie man sagt) "am Ende des Tages" - es ist viel einfacher, einen Heap-Profiler wie Valgrind zu verwenden und die damit verbundenen Werkzeuge ( Massif ) in diesem Fall, die Ihnen eine Menge Informationen geben werden. In diesem speziellen Fall hätte Valgrind auf das Offensichtliche hingewiesen - Sie haben über die zugewiesene Grenze geschrieben. In den meisten Fällen jedoch, wenn dies nicht beabsichtigt ist, ist ein guter Profiler / Fehlerdetektor von unschätzbarem Wert.
Die Verwendung eines Profilers ist nicht immer möglich aufgrund:
malloc()
abgefangen werden). malloc()
) müssen ein integraler Bestandteil des Programms sein Wir haben eine Variante der Bibliothek verwendet, die ich in HelenOS verlinkt habe (ich bin mir nicht sicher, ob sie es immer noch benutzt), da das Debugging am VMM dafür bekannt war, Wahnsinn zu verursachen.
Denken Sie immer noch gründlich über künftige Auswirkungen nach, wenn Sie einen Ersatzrückgang in Erwägung ziehen, wenn es um die Einrichtung malloc()
geht, die Sie fast immer verwenden möchten, was das System liefert.
Wie viel malloc intern zuweist, ist implementierungsabhängig und betriebssystemabhängig (z. B. ein Vielfaches von 8 Bytes oder mehr). Ihr Schreiben in die nicht zugewiesenen Bytes kann dazu führen, dass die Werte anderer Variablen überschrieben werden, selbst wenn Ihr Compiler und die Laufzeit den Fehler nicht erkennen. Die Frei-Funktion merkt sich die Anzahl der zugewiesenen Bytes getrennt von der zugewiesenen Region, zum Beispiel in einer freien Liste.
Warum gibt mir der Compiler nicht ein? Fehler, mir zu sagen, dass es nicht genug ist Speicher zugewiesen?
C
blockiert nicht die Verwendung von Speicher, den Sie nicht verwenden sollten. Sie können diesen Speicher verwenden, aber er ist schlecht und führt zu einem nicht definierten Verhalten. Sie schreiben an einem Ort, den Sie nicht sollten. Dieses Programm wird möglicherweise korrekt ausgeführt, kann jedoch später abstürzen. Das ist UB
. Sie wissen nicht, was passieren könnte.
Das passiert mit deinem strcpy()
. Du schreibst an Stelle, die du nicht besitzt, aber die Sprache schützt dich davor nicht. Sie sollten also sicherstellen, dass Sie immer wissen, was und wo Sie schreiben, oder stellen Sie sicher, dass Sie aufhören, wenn Sie gültige Speichergrenzen überschreiten.
Ich lese ein paar Fragen, die fragen Wie überprüft man, wie viel Speicher malloc eigentlich zuweist, aber ich habe kein gefunden konkrete Antwort. Sollte nicht die "freie" Funktion müssen wissen, wie viel Speicher ist genau 'Puffer' zugeordnet?
malloc()
könnte mehr Speicher zuweisen, als Sie wegen der Bit-Auffüllung anfordern.
Mehr: Ссылка
free()
gibt den genau gleichen Betrag frei, den Sie mit malloc()
zugewiesen haben, aber es ist nicht so schlau wie Sie denken. ZB:
Sie sollten immer free()
einen Zeiger angeben, der auf den ersten Block zeigt. Doing a free(0)
ist sicher.
Sie haben über das Ende des reservierten Puffers hinaus geschrieben. Das Ergebnis ist ein nicht definiertes Verhalten. Einige Laufzeitbibliotheken mit den richtigen Optionen haben zumindest eine gewisse Fähigkeit, solche Probleme zu diagnostizieren, aber nicht alle, und sogar solche, die dies nur zur Laufzeit tun, und normalerweise nur dann, wenn sie mit den richtigen Optionen kompiliert wurden.
>Malloc - & gt; Wie viel Speicher wurde zugewiesen?
Wenn Sie Speicher mithilfe von malloc zuweisen. Bei Erfolg weist es Speicher zu und die Standardzuweisung beträgt 128 KB. Der erste Anruf bei malloc gibt Ihnen 128k.
Was Sie angefordert haben, ist buffer = malloc (2);
Obwohl Sie 2 Bytes angefordert haben. Es hat 128k zugewiesen.
strcpy(buffer, "hello");
Zugewiesene 128k Chunk begann die Bearbeitung Ihrer Anfrage. "Hallo"
String kann hineinpassen.
Dieser pgm wird Ihnen klar machen.
%Vor% für (; i & lt; 5; i ++, p ++) enter code here
printf ("% d \ t", * p);
Beim ersten Aufruf von malloc. Es weist 128k --- & gt; Von diesem verarbeitet es Ihre Anfrage (2 Bytes). Die Zeichenfolge "Hallo" kann hineinpassen. Wieder beim zweiten Aufruf von malloc verarbeitet sie Ihre Anfrage von 128k.
Beyond 128k verwendet es mmap-Schnittstelle. Sie können auf die man-Seite von malloc verweisen.
Es gibt keinen Compiler / Plattform-unabhängigen Weg herauszufinden, wie viel Speicher malloc tatsächlich zugewiesen hat. malloc wird im Allgemeinen etwas mehr Zuteilung als Sie es verlangen, hier sehen:
Unter Linux können Sie malloc_userable_size verwenden, um herauszufinden, wie viel Speicher Sie verwenden können. Auf MacOS und anderen BSD-Plattformen können Sie malloc_size verwenden. Der oben verlinkte Beitrag enthält vollständige Beispiele für beide Techniken.
Tags und Links c memory-management malloc