Ist es überhaupt OK, um *nicht* verwenden, free() auf zugewiesenen Speicher?
Studiere ich informatik, und ich habe einige Elektronik-Kurse. Ich hörte, von zwei meiner Professoren (diese Kurse), dass es möglich ist zu vermeiden, mit den free()
- Funktion (nach malloc()
, calloc()
usw.) da die Speicherbereiche zugewiesen wird wahrscheinlich nicht wieder verwendet werden, zuweisen, anderen Speicher. Das heißt, zum Beispiel, wenn Sie reservieren Sie 4 bytes und dann die Freigabe, die Sie haben werden 4 Byte an Speicherplatz, die wahrscheinlich nicht noch einmal vergeben: Sie haben eine Loch.
Ich denke, dass ist verrückt: man kann nicht ein nicht-Spielzeug-Programm, wo man Speicher auf dem heap, ohne es loszulassen. Aber ich habe nicht das wissen haben, genau zu erklären, warum es so wichtig ist, dass für jede malloc()
es muss eine free()
.
Also: gibt es überhaupt Umstände, unter denen es angebracht sein könnte, zu verwenden malloc()
ohne Verwendung free()
? Und wenn nicht, wie kann ich das erklären meine Professoren?
- Ich bekomme Ihren Punkt, der Sie darauf hingewiesen werden, wenn Sie versuchen zu reservieren zusammenhängender Speicher Speicher später, es wird wahrscheinlich nicht verwenden diese Adresse, da ist es nur ein kleiner zusammenhängender block. Aber wie du und andere, stellte fest, es ist eine schlechte Praxis. Es verliert Speicher und plus, die Adresse könnte zur Verfügung, für nicht-zusammenhängenden Speicher (wie verlinkte Listen)
- Sie sind nicht "falsch" - Sie haben eine gültige (wenn auch begrenzten) Standpunkt über die Fragmentierung von sehr kleinen isolierten freien Regionen, und wahrscheinlich erklärt es ein wenig genauer, als Sie es gemeldet.
- Die einzige Zeit, die Sie nicht brauchen, um Speicher frei ist bei der Verwendung von verwalteten Speicher oder, wenn Sie gehen, um die Wiederverwendung der ursprünglichen zugewiesenen Speicher. Ich vermute, dass der Grund zwei Lehrer haben gesagt, dass dies, weil Sie sprechen von einem speziellen Programm, welches die Wiederverwendung der Speicher. In diesem Fall würden Sie immer noch verwenden, free (), sondern nur am Ende der Anwendung. Sind Sie sicher, dass das nicht Ihre Bedeutung?
- Ich hatte einen professor behaupten, dass in C und C++ ist es notwendig, frei Ihre zugewiesenen Speicher in einer Funktion definiert, in der gleichen .c/.cxx-Datei, wie Sie vergeben war... Diese Leute scheinen manchmal zu stark leiden unter Hypoxie aufgrund von Wohn-zu hoch in einem Elfenbein-Turm.
- Ich würde sagen, ein speicherreservierungsfunktion Griff Fragmentierung in den meisten der Fälle & das ist, warum Sie sollten frei Ihr Gedächtnis.
- Es gibt durchaus ein paar nicht-Spielzeug-Programme, die keinen Speicher freigeben, und lassen Sie den OS-reinigen Sie alle bis auf Prozess beenden ist wesentlich schneller als (fussily) halten viel von Buchhaltung, so dass Sie können es selbst tun.
- Auch "es ist möglich, vermeiden
free()
" ist deutlich anders als, z.B. "es macht manchmal keinen Unterschied, wenn Sie anrufenfree()
", sind Sie sicher, dass Ihre Professoren sagte der ehemalige? - Als hingewiesen durch @mfro
free()
nicht zurück-Speicher für das OS, aber dennoch markiert Sie für die Wiederverwendung durchmalloc()
. Dieses verschieben künftige Aufrufemmap()/sbrk()
, zu konservieren und system-Speicher. Mal ganze Seiten, die ungenutzt erhalten Sie ausgelagert. Prozesse mit langer Lebensdauer sollten allerdings dieses Problem anzugehen und tatsächlich zurück-Speicher für das OS (leichter bei der Verwendung vonmmap()
alsbrk()
, aber es ist so viel einfacher, nur ein Neustart ein Prozess. Dies ist, wo Entwicklung und Betrieb, müssen die Zusammenhänge zu verstehen. - Nie Zusammenführen Sachen, die Sie hören, in Ihrem Gehirn, keine Frage. Ich hatte schon viele Lehrer und Dozenten und Korrektoren, die falsch waren oder out-of-date. Und immer analysieren, was Sie sagen sehr genau. Unser Volk ist oft sehr präzise und kann sagen, dass Zeug, das ist richtig, aber ist leicht zu verstehen, falsch oder mit der falschen Priorität von jemandem, der fühlt sich zu Hause nur im Allgemeinen Sprachgebrauch. E. g., Ich erinnere mich, in der Schule, eine Lehrerin sagte: "Hast du deine Hausaufgaben machen.", Ich sagte: "Nein.". Während ich war auf der richtigen, der Lehrer fand diese offensive, weil ich mich gerettet, die Zeit zu finden, lahme Ausreden, die er nicht erwartet hat.
- Während die Befreiung in der selben compilation unit ist nicht erforderlich, die kostenlos wirklich sein sollte in der gleichen Bibliothek wie die Zuordnung, die möglicherweise durch die explizit herausstellen eines deallocator. Das gilt besonders für shared-libraries. Unter der Annahme, dass die "free" - von der Basis-Programm ist kompatibel mit der "malloc" in einer Bibliothek verwendet werden, ist nicht sicher. Es kann auch Ergebnis, nicht die Verwendung einer API aus einer anderen Sprache, ohne Speicherverlust, da diese Sprachen nicht haben Zugang zu den gleichen "frei".
- Schon komisch, dass in den vergangenen zwei Jahrzehnten, die ich hatte nie irgendwelche Probleme damit, und anscheinend fast alle software, die auf linux nicht zu. Ist das vielleicht ein Mythos, der schleichende, von außergewöhnlichen fehlerhafte Implementierungen? Da der standard nicht verlangen, dass diese eine Sache, die ich nennen würde, solche Implementierungen nicht konform und gebrochen.
- Sicher, aber shared-Bibliotheken sind noch nicht einmal berücksichtigt, indem die Sprache, die Normen, um mit zu beginnen, so ist Undefiniertes Verhalten. Ziemlich große Anwendungen, die unter windows laufen, ist oft ein Minimum von zwei verschiedenen malloc-Implementierungen, die können-müssen aber nicht-zu kooperieren. Weitere, auch unter linux Programme und shared libraries sind frei, verwenden Sie eine C-Bibliothek andere als die libc.so, wie eine statische libc, oder Alternative Implementierung. Es kann wirklich lästig/teuer zu reparieren, wenn eine Bibliothek macht diese Annahme, aber die Umgebung nicht zulässt.
- Ich bin sicher, Sie haben das falsch verstanden, das Thema. Sie waren entweder zu sagen, Sie vermeiden mallocing/Befreiung der kleinen Speicherblöcke, oder die Wiederverwendung der Blöcke im Speicher, wenn möglich.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einfach: Lesen Sie die Quelle von so ziemlich jede halbwegs ernsthafte
malloc()/free()
Umsetzung. Damit meine ich die tatsächlichen Speicher-manager, dass Griffe die Arbeit der Anrufe. Dies könnte in der runtime-Bibliothek, der virtuellen Maschine oder des Betriebssystems. Natürlich ist der code nicht gleichermaßen zugänglich für alle Fälle.Sicherstellen, dass Speicher nicht fragmentiert ist, durch den Beitritt der angrenzenden Löcher in größere Löcher, ist sehr sehr Häufig. Ernster allocators verwenden Sie mehr seriöse Techniken, um dies sicherzustellen.
So, nehmen wir an, Sie tun drei Zuweisungen und de-Zuweisungen und bekommen die Blöcke layed out in Speicher in dieser Reihenfolge:
Die Größen der einzelnen Zuweisungen sind nicht wichtig. Sie dann frei der erste und Letzte, A und C:
wenn Sie endlich frei B, Sie (anfangs, zumindest in der Theorie) am Ende mit:
werden kann de-fragmentiert in nur
d.h. einem einzigen größeren freien block, keine Fragmente übrig.
Referenzen wie gewünscht:
heap4.c
- code in FreeRTOS.malloc
- Implementierung in Windows werden völlig nutzlos. Sehen Sie nur einen Anruf zuHeapAlloc
, dessen Quelle Sie nicht Lesen können...Den anderen Antworten schon erklären ganz genau, dass Reale Implementierungen von
malloc()
undfree()
tatsächlich coalesce (defragmnent) Löcher in größere freie Stücke. Aber selbst wenn das nicht der Fall war, wäre es immer noch eine schlechte Idee zu verzichtenfree()
.Die Sache ist die, dass Ihr Programm nur reserviert (und will frei) diese 4 Byte Speicher. Wenn es ausgeführt wird, für einen längeren Zeitraum, ist es ziemlich wahrscheinlich, dass es Notwendigkeit zu vergeben nur 4 Byte Speicher wieder. Also selbst wenn diese 4 bytes werden niemals verschmelzen Sie zu einem größeren zusammenhängenden Raum, können Sie immer noch wieder verwendet werden, indem das Programm selbst.
free
aufgerufen wird, ist oft genug, um einen Einfluss auf die Leistung, dann ist es wohl auch genannt wird, oft genug so, dass man es machen wird, eine sehr große Beule im verfügbaren Speicher. Es ist schwer eine situation vorstellen, auf einem embedded-system wo Leistung ständig leidet aufgrundfree
aber womalloc
ist nur eine endliche Anzahl von malen; es ist ein ziemlich seltener Fall sein, um ein embedded Gerät, das die one-shot-Verarbeitung der Daten wird dann zurückgesetzt.Es ist totaler Quatsch, es gibt zum Beispiel viele verschiedene Implementierungen von
malloc
einige versuchen zu machen heap effizienter wie Doug Lea ' s oder diese ein.Sind Ihre Professoren arbeiten mit POSIX, durch Zufall? Wenn Sie gewohnt sind, zu schreiben, viele kleine, minimalistische shell Anwendungen, das ist ein Szenario, wo ich mir vorstellen kann, dieser Ansatz wäre nicht allzu schlimm - die Befreiung der ganze Haufen auf einmal an der Freizeit des OS ist schneller als zu befreien, ein tausend Variablen. Wenn Sie erwarten, dass Ihre Anwendung für eine Sekunde oder zwei, können Sie leicht Weg mit kein de-Allokation an alle.
Es ist immer noch eine schlechte Praxis natürlich (performance-Verbesserungen sollte es immer sein, basierend auf profiling, nicht vage Bauchgefühl), und es ist nicht etwas, was Sie sagen sollte, um die Schüler ohne zu erklären, die anderen Einschränkungen, aber ich kann mir vorstellen, eine Menge von kleinen-Rohrleitungen-shell-Anwendungen geschrieben werden, auf diese Weise (wenn nicht mit statischen Zuordnung geradezu). Wenn Sie an etwas arbeiten, dass die Vorteile aus nicht befreien, Ihre Variablen, bist du entweder arbeiten, in der extreme low-latency-Bedingungen (in dem Fall, wie kann Sie selbst sich leisten, die dynamische Zuweisung und C++? :D), oder du tust etwas sehr, sehr falsch (wie die Zuweisung einer integer-array durch die Zuweisung tausend Ganzzahlen, eine nach der anderen, anstatt einem einzigen block des Speichers).
Sie erwähnt, Sie waren-Elektronik-Professoren. Sie kann verwendet werden, um das schreiben der firmware/Echtzeit-software, waren in der Lage, präzise Zeit-jährigen die Ausführung ist Häufig erforderlich. In diesen Fällen wissen, haben Sie genug Speicher für alle Zuweisungen-und nicht die Befreiung und die Neuzuweisung von Speicher kann ein leichter berechnete limit für die Ausführungszeit.
In manchen Systemen hardware-Speicherschutz kann auch verwendet werden, um sicherzustellen, dass die routine abgeschlossen in seinem zugeordneten Speicher oder generiert einen trap, was sollte sehr Ausnahmefällen.
malloc
und solches in diesem Fall, statt sich auf statische Zuweisung (oder vielleicht reservieren Sie sich ein großes Stück und dann manuell fassen Sie das Speichermodul).Wobei diese aus einem anderen Blickwinkel als die bisherigen Kommentatoren und Antworten, eine Möglichkeit ist, dass Ihre Professorinnen und Professoren haben bereits Erfahrung mit Systemen, bei denen Speicher zugewiesen wurde statisch(sprich: wenn das Programm kompiliert wurde).
Statische Zuteilung kommt, wenn Sie Dinge tun, wie:
In viele Echtzeit-und embedded Systeme(am ehesten begegnet werden durch EBS oder CEs), ist es in der Regel besser zu vermeiden, die die dynamische Speicherverwaltung zusammen. Also, nutzt der
malloc
,new
, und deren Löschung Kollegen sind selten. Auf top von, dass, Speicher im Computer, in den letzten Jahren explodiert.Wenn du noch 512 MB zur Verfügung, und Sie statisch zuweisen 1 MB, Sie haben etwa die 511 MB zu ziehen durch, bevor Sie Ihre software explodiert(gut, nicht genau...aber die gehn bei mir hier). Vorausgesetzt, Sie haben 511 MB zu missbrauchen, wenn Sie malloc 4 bytes jede Sekunde ohne diese Freigabe, werden Sie in der Lage zu laufen, für knapp 73 Stunden bevor Sie laufen out of memory. Angesichts vieler Maschinen abgeschaltet, sobald ein Tag, das bedeutet, dass dein Programm wird nie aus der Erinnerung!
Im obigen Beispiel, das Leck ist 4 bytes pro Sekunde oder 240 bytes/min. Nun stellen Sie sich vor, dass Sie niedrigere byte/min-Verhältnis. Das niedriger das Verhältnis, desto länger Ihr Programm ausführen kann, ohne Probleme. Wenn Ihr
malloc
s selten, dass eine Reale Möglichkeit ist.Solls, wenn Sie wissen, Sie sind nur gehen, um
malloc
einmal etwas, und dasmalloc
wird nie wieder schlagen, dann ist es ein viel wie die statische Zuordnung, obwohl Sie brauchen nicht zu wissen, die Größe, was es ist, du bist die Zuteilung vor. ZB: nehmen wir an, wir haben 512 MB wieder. Wir müssenmalloc
32 arrays von ganzen zahlen. Dies sind typische Integer - 4 Byte. Wir kennen die Größe dieser arrays wird nie mehr als 1024 Integer-zahlen. Keine andere Speicherzuordnungen, die auftreten, in unserem Programm. Tun wir genug Speicher haben? 32 * 1024 * 4 = 131,072. 128 KB - also ja. Wir haben viel Platz. Wenn wir wissen, dass wir nie reservieren Sie mehr Speicher, können wir sichermalloc
diese arrays ohne diese Freigabe. Dies kann jedoch auch bedeuten, dass Sie müssen neu starten, die Maschine/Gerät, wenn ein Programm abstürzt. Wenn Sie beginnen/stoppen Sie Ihr Programm von 4.096 mal, du wirst zuordnen, alle 512 MB. Wenn Sie zombie-Prozesse es ist möglich, dass der Speicher wird nie freigegeben werden, auch nach einem Absturz.Sparen Sie sich den Schmerz und Elend, und verbrauchen dieses mantra als Eine Wahrheit:
malloc
sollte immer Zusammenhang mit einerfree
.new
sollte immer haben einedelete
.sizeof(int)
gleich 2 eher 4.Ich denke, der Anspruch, erklärte in der Frage ist Unsinn, wenn Sie wörtlich genommen aus der programmer ' s Standpunkt, aber es hat die Wahrheit (zumindest einige) das Betriebssystem anzeigen.
malloc() wird schließlich durch den Aufruf mmap() oder sbrk() und holt sich die Seite vom OS.
In jedem nicht-trivialen Programm, die Chancen, dass diese Seite immer wieder dem OS während eines Prozesse die Lebensdauer sind sehr klein, selbst wenn Sie frei() die meisten von den zugewiesenen Speicher. So free()'d Speicher wird nur für den gleichen Prozess die meiste Zeit, aber nicht auf andere.
Ihre Professoren sind nicht falsch, aber auch sind (Sie sind zumindest irreführend oder zu kurz gedacht). Fragmentierung des Speichers führt zu Problemen für die Leistung und die effiziente Nutzung von Speicher, so dass Sie manchmal haben, Sie zu prüfen und Maßnahmen ergreifen, um es zu vermeiden. Ein klassischer trick ist, wenn Sie zuordnen, viele Dinge, die die gleiche Größe haben, greifen auf einen pool von Speicher auf startup, das einige mehrere von dieser Größe und Verwaltung Ihrer Nutzung ausschließlich intern, also sicherstellen, dass Sie don ' T haben die Fragmentierung geschieht auf der OS-Ebene (und die Löcher in den internen Speicher-mapper, genau die richtige Größe für das nächste Objekt dieses Typs, die entlang kommt).
Gibt es ganze Bibliotheken von Drittanbietern, die nichts tun, sondern behandeln, dass Art der Sache für Sie, und manchmal ist es der Unterschied zwischen der akzeptablen Leistung und etwas, das läuft viel zu langsam.
malloc()
undfree()
nehmen eine erhebliche Menge an Zeit ausführen, die Sie beginnen zu bemerken, wenn Sie anrufen, Ihnen eine Menge.Also durch die Vermeidung nur naiv mit
malloc()
undfree()
vermeiden Sie sowohl die Fragmentierung und performance-Probleme - aber wenn Sie rechts unten, um es zu, Sie sollten immer sicherstellen, dass Siefree()
alles, was Siemalloc()
es sei denn, Sie haben einen sehr guten Grund, es anders zu machen. Auch bei der Verwendung eines internen Speicher-pool eine gute Bewerbung istfree()
den Speicher-pool, bevor es beendet wird. Ja, das OS wird es sauber, aber wenn das application lifecycle später geändert, es würde leicht sein, zu vergessen, dass der pool noch hanging around...Lange laufende Anwendungen, die natürlich sein müssen, äußerst gewissenhaft über die Reinigung oder Verwertung alles, was Sie haben zugeteilt, oder Sie wird aus dem Speicher.
Ihre Professoren zu erziehen sind ein wichtiger Punkt. Leider ist die Nutzung der englischen Sprache ist so, dass ich bin nicht absolut sicher, was es ist, sagten Sie. Lassen Sie mich die Frage beantworten, in Bezug auf nicht-Spielzeug-Programme, die eine bestimmte Speicherauslastung Eigenschaften, und dass ich persönlich, arbeitete mit.
Einige Programme Verhalten sich sehr schön. Sie reserviert Speicher in Wellen: viele kleine oder mittelständische Zuweisungen, gefolgt von vielen befreit, in sich wiederholenden Zyklen. In diesen Programmen typische Speicherzuordnungen sehr gut. Sie verschmelzen befreit Blöcke und am Ende einer Welle, die die meisten gratis-Speicher in große zusammenhängende Stücke. Diese Programme sind Recht selten.
Meisten Programme, die sich schlecht Verhalten. Sie reservieren und freigeben von Speicher mehr oder weniger zufällig, in einer Vielzahl von Größen, von sehr klein zu sehr groß, und Sie behalten eine hohe Auslastung der zugewiesenen Blöcke. In diesen Programmen wird die Fähigkeit zum verschmelzen der Blöcke begrenzt ist, und über Zeit, die Sie beenden mit der Speicher stark fragmentiert und relativ nicht-zusammenhängend. Wenn die gesamte Speichernutzung von über etwa 1,5 GB in ein 32-bit memory space, und es gibt Zuteilungen von (sagen wir) 10 MB oder mehr, schließlich einer der großen Zuweisungen fehlschlagen. Diese Programme sind Häufig.
Andere freie Programme wenig oder gar keine Speicher, bis Sie zu stoppen. Sie progressiv Speicher, während der Ausführung, zu befreien, nur kleine Mengen, und dann aufhören, zu welchem Zeitpunkt alle Speicher freigegeben wird. Ein compiler ist, wie dieses. So eine VM ist. Zum Beispiel, die .NET CLR-Laufzeitumgebung, selbst in C++ geschrieben, die wohl nie freigegeben Speicher. Warum sollte es?
Und das ist die endgültige Antwort. In jenen Fällen, wo das Programm ist hinreichend schwer, Speicherauslastung, dann Speicherverwaltung mit malloc und free ist keine ausreichende Antwort auf das problem. Es sei denn, Sie Glück genug, um den Umgang mit eine gut konzipierte Programm, werden Sie brauchen, um design eine oder mehrere benutzerdefinierte memory-allocators, die pre-allocate große Brocken Speicher und dann sub-zuordnen, nach einer Strategie Ihrer Wahl. Sie können nicht frei verwenden, außer wenn das Programm nicht.
Ohne genau zu wissen, was Ihre Professoren sagten, für wahrhaft Produktions-scale-Programme, die ich würde wahrscheinlich kommen auf Ihre Seite.
BEARBEITEN
Werde ich einen gehen Sie bei der Beantwortung einige der Kritikpunkte. Offensichtlich ist ALSO kein guter Platz für Beiträge dieser Art. Nur um klar zu sein: ich habe rund 30 Jahre Erfahrung schriftlich diese Art von software, einschließlich ein paar von Compilern. Ich habe keine akademischen Referenzen, nur meine eigenen blauen Flecken. Ich kann mir nicht helfen Gefühl, die Kritik komme von Leuten, die mit weit enger und kürzer zu erleben.
Ich wiederhole meine zentrale Botschaft: Vereinbarkeit von malloc und free ist nicht eine ausreichend große Lösung für scale-memory-Allokation in Reale Programme. Block Koaleszenz ist normal, und kauft Zeit, aber es ist nicht genug. Sie brauchen ernsthafte, klug memory allocators, die in der Regel grab Speicher in Blöcken (mit malloc oder was auch immer) und kostenlos nur selten. Dies ist wahrscheinlich die Nachricht OP Professorinnen und Professoren im Sinn hatte, die er falsch verstanden.
VirtualAlloc
eine Menge (aus meiner Beobachtung fast ausschließlich), aber das spielt eigentlich keine Rolle - am Ende ist es reservieren und freigeben von Speicher. Ich kann nicht sprechen über die JVM (oder einer der gegebenen Implementierungen), von meiner (sehr begrenzten) Beobachtungen schien es, dass es in der Tat nicht der freie Speicher. Aber es gibt eine Menge von JVMs.Ich bin überrascht, dass niemand zitiert hatte Das Buch noch:
http://sarabander.github.io/sicp/html/5_002e3.xhtml#FOOT298
So, in der Tat, viele Programme können tun just fine, ohne jemals belästigen zu Speicher frei.
Ich kennen einen Fall, in dem explizit freigeben von Speicher ist schlimmer als nutzlos. Das ist, wenn Sie müssen alle Ihre Daten, bis das Ende der Prozess Lebensdauer. In anderen Worten, wenn diese Freigabe ist nur möglich, rechts vor der Beendigung des Programms. Da jedes moderne Betriebssystem nimmt freigeben von Speicher, wenn ein Programm stirbt, ruft
free()
ist nicht notwendig in diesem Fall. In der Tat, es möglicherweise verlangsamen Beendigung des Programms, da kann es brauchen, ist der Zugriff auf mehrere Seiten im Speicher.