Ich verstehe, dass Rust keinen Garbage Collector hat und frage mich, wie Speicher freigegeben wird, wenn eine Bindung außerhalb des Gültigkeitsbereichs liegt.
In diesem Beispiel verstehe ich, dass Rust den 'a' zugewiesenen Speicher zurückfordert, wenn er außerhalb des Gültigkeitsbereichs liegt.
{
let a = 4
}
Das Problem, das ich damit habe, ist zum einen, wie das passiert, und zum anderen ist das nicht eine Art Müllsammlung? Wie unterscheidet es sich von der "typischen" Speicherbereinigung?
Antworten:
Die Speicherbereinigung wird normalerweise regelmäßig oder bei Bedarf verwendet, z. B. wenn der Heap nahezu voll ist oder einen bestimmten Schwellenwert überschreitet. Es sucht dann nach nicht verwendeten Variablen und gibt je nach Algorithmus Speicher frei .
Rust würde wissen, wann die Variable den Gültigkeitsbereich verlässt oder ihre Lebensdauer zur Kompilierungszeit endet, und daher die entsprechenden LLVM- / Assembly-Anweisungen einfügen, um den Speicher freizugeben.
Rust erlaubt auch eine Art Garbage Collection, wie das Zählen von Atomreferenzen.
quelle
new()
Funktion wie C, es sind nur statische Funktionen, und insbesondere so etwas wie daslet x = MyStruct::new()
Erstellen seines Objekts auf dem Stapel. Der eigentliche Indikator für die Heap-Zuordnung istBox::new()
(oder eine der Strukturen, die von Box abhängen).Die Grundidee beim Verwalten von Ressourcen (einschließlich Speicher) in einem Programm, unabhängig von der Strategie, besteht darin, dass die an nicht erreichbare "Objekte" gebundenen Ressourcen zurückgefordert werden können. Über den Speicher hinaus können diese Ressourcen Mutex-Sperren, Dateihandles, Sockets, Datenbankverbindungen ... sein.
Sprachen mit einem Garbage Collector durchsuchen den Speicher regelmäßig (auf die eine oder andere Weise), um nicht verwendete Objekte zu finden, die damit verbundenen Ressourcen freizugeben und schließlich den von diesen Objekten verwendeten Speicher freizugeben.
Rust hat keinen GC, wie geht das?
Rust hat Eigentum. Unter Verwendung eines affinen Typsystems verfolgt es, welche Variable noch an einem Objekt festhält, und ruft ihren Destruktor auf, wenn eine solche Variable den Gültigkeitsbereich verlässt. Sie können das affine Typsystem ziemlich leicht erkennen:
Ausbeuten:
Dies zeigt perfekt, dass zu jedem Zeitpunkt auf Sprachebene der Besitz nachverfolgt wird.
Dieser Besitz funktioniert rekursiv: Wenn Sie einen
Vec<String>
(dh ein dynamisches Array von Zeichenfolgen) haben, gehört jederString
dem,Vec
der selbst einer Variablen oder einem anderen Objekt gehört, usw. Wenn eine Variable den Gültigkeitsbereich verlässt, es setzt rekursiv alle Ressourcen frei, die es besaß, auch indirekt. Im Falle derVec<String>
bedeutet dies:String
Vec
selbst zugeordneten SpeicherpuffersDank der Besitzverfolgung ist die Lebensdauer ALLER Programmobjekte streng an eine (oder mehrere) Funktionsvariablen gebunden, die letztendlich den Gültigkeitsbereich verlassen (wenn der Block, zu dem sie gehören, endet).
Hinweis: Dies ist etwas optimistisch, da durch Referenzzählung (
Rc
oderArc
) Referenzzyklen gebildet werden können und somit Speicherlecks verursacht werden. In diesem Fall werden die an den Zyklus gebundenen Ressourcen möglicherweise nie freigegeben.quelle
Bei einer Sprache, in der Sie den Speicher manuell verwalten müssen, wird die Unterscheidung zwischen dem Stapel und dem Heap kritisch. Jedes Mal, wenn Sie eine Funktion aufrufen, wird auf dem Stapel genügend Speicherplatz für alle Variablen zugewiesen, die im Bereich dieser Funktion enthalten sind. Wenn die Funktion zurückkehrt, wird der dieser Funktion zugeordnete Stapelrahmen vom Stapel "geknallt" und der Speicher für die zukünftige Verwendung freigegeben.
Aus praktischer Sicht wird diese versehentliche Speicherbereinigung als Mittel zur automatischen Speicherung von Speicher verwendet, der am Ende des Funktionsumfangs gelöscht wird.
Weitere Informationen finden Sie hier: https://doc.rust-lang.org/book/the-stack-and-the-heap.html
quelle