Erzwingt die Reihenfolge, in der Strukturfelder gelöscht werden

8

Ich implementiere ein Objekt, das mehrere Ressourcen besitzt, die von C-Bibliotheken über FFI erstellt wurden. Um zu bereinigen, was bereits gemacht wurde, wenn der Konstruktor in Panik gerät, wickle ich jede Ressource in eine eigene Struktur und implementiere Drop für sie. Wenn es jedoch zum Löschen des Objekts selbst kommt, kann ich nicht garantieren, dass Ressourcen in einer sicheren Reihenfolge abgelegt werden, da Rust die Reihenfolge der Felder einer Struktur nicht definiert.

Normalerweise würden Sie dies lösen, indem Sie es so einrichten, dass das Objekt nicht die Ressourcen besitzt, sondern es ausborgt (damit sich die Ressourcen gegenseitig ausborgen). Im Endeffekt schiebt sich das Problem auf den aufrufenden Code zu, wo die Drop-Reihenfolge gut definiert ist und mit der Semantik des Ausleihens durchgesetzt wird. Aber das ist unpassend für meinen Anwendungsfall und im Allgemeinen ein bisschen Ausreden.

Was ärgerlich ist, ist, dass dies unglaublich einfach wäre, wenn drop aus irgendeinem Grund self anstelle von &mut self verwendet hätte. Dann könnte ich einfach std::mem::drop in meiner gewünschten Reihenfolge aufrufen.

Gibt es eine Möglichkeit, dies zu tun? Wenn nicht, gibt es eine Möglichkeit, im Falle einer Panik des Konstrukteurs aufzuräumen, ohne sie manuell zu erfassen und erneut zu bearbeiten?

    
jmegaffin 09.12.2016, 05:15
quelle

1 Antwort

10

Sie können die Reihenfolge der Reihenfolge Ihrer Strukturfelder auf zwei Arten festlegen:

Implizit

Ich schrieb RFC 1857 , um die Reihenfolge anzugeben und es wurde am 03.07.2017 verschmolzen! Nach dem RFC werden Strukturfelder in derselben Reihenfolge abgelegt, wie sie deklariert sind.

Sie können dies überprüfen, indem Sie das Beispiel unten

ausführen %Vor%

Die Ausgabe sollte lauten:

%Vor%

Explizit

RFC 1860 führt das ManuallyDrop Typ, der einen anderen Typ umschließt und dessen Destruktor deaktiviert. Die Idee ist, dass Sie das Objekt manuell löschen können, indem Sie eine spezielle Funktion aufrufen ( ManuallyDrop::drop ). Diese Funktion ist nicht sicher, da der Speicher nach dem Löschen des Objekts nicht initialisiert ist.

Sie können ManuallyDrop verwenden, um die Reihenfolge der Felder Ihrer Felder im Destruktor Ihres Typs explizit anzugeben:

%Vor%

Wenn Sie dieses Verhalten benötigen, ohne eine der neueren Methoden verwenden zu können, lesen Sie weiter ...

Das Problem mit dem Drop

Die Methode drop kann ihren Parameter nicht als Wert annehmen, da der Parameter am Ende des Bereichs wieder fallen würde. Dies würde zu einer unendlichen Rekursion für alle Destruktoren der Sprache führen.

Eine mögliche Lösung / Abhilfe

Ein Muster, das ich in einigen Codebasen gesehen habe, besteht darin, die Werte, die in Option<T> fallengelassen werden, zu umbrechen. Anschließend können Sie im Destruktor jede Option durch None ersetzen und den resultierenden Wert in der richtigen Reihenfolge löschen.

Zum Beispiel in der Scoped-threadpool -Kiste Das Pool -Objekt enthält Threads und einen Sender, der neue Arbeit plant. Um die Threads beim Ablegen korrekt zu verbinden, sollte zuerst der Absender und dann der Thread fallengelassen werden.

%Vor%

Ein Hinweis zur Ergonomie

Natürlich ist es eher eine Umgehung als eine richtige Lösung, die Dinge auf diese Weise zu erledigen. Wenn das Optimierungsprogramm nicht beweisen kann, dass die Option immer Some ist, haben Sie jetzt eine zusätzliche Verzweigung für jeden Zugriff auf Ihr Strukturfeld.

Glücklicherweise verhindert nichts, dass eine zukünftige Version von Rust ein Feature implementiert, das die Festlegung der Reihenfolge ermöglicht. Es würde wahrscheinlich einen RFC erfordern, scheint aber durchaus machbar. Es gibt eine fortlaufende Diskussion über den Issue Tracker zum Festlegen der Drop-Reihenfolge für die Sprache, obwohl diese inaktiv war letzten Monaten.

Ein Sicherheitshinweis

Wenn das Zerstören Ihrer Strukturen in der falschen Reihenfolge unsicher ist, sollten Sie in Betracht ziehen, ihre Konstruktoren unsafe zu erstellen und diese Tatsache zu dokumentieren (falls Sie das nicht bereits getan haben). Andernfalls wäre es möglich, unsicheres Verhalten nur durch Erstellen der Strukturen auszulösen und sie außerhalb des Gültigkeitsbereichs fallen zu lassen.

    
aochagavia 09.12.2016, 09:06
quelle

Tags und Links