Das Entdecken von unsicheren Operationen in Rust

RustRustBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab werden wir uns mit unsicheren Operationen in Rust befassen, die verwendet werden, um Compiler-Schutzmechanismen zu umgehen und typischerweise für das Dereferenzieren von rohen Zeigern, das Aufrufen unsicherer Funktionen, das Zugreifen auf oder Ändern von statischen veränderlichen Variablen und das Implementieren unsicherer Traits verwendet werden. Diese Operationen sollten in einer Codebasis minimiert werden, um die Sicherheit zu gewährleisten.

Hinweis: Wenn das Lab keinen Dateinamen angibt, können Sie einen beliebigen Dateinamen verwenden. Beispielsweise können Sie main.rs verwenden und es mit rustc main.rs &&./main kompilieren und ausführen.

Unsichere Operationen

Als Einführung in diesen Abschnitt, um von den offiziellen Dokumentationen zu zitieren: "Man sollte versuchen, die Menge an unsicherem Code in einer Codebasis zu minimieren." Im Licht dessen, fangen wir an! Unsichere Anmerkungen in Rust werden verwendet, um die von dem Compiler eingeführten Schutzmechanismen zu umgehen; genauer gesagt, gibt es vier Hauptsachen, für die unsafe verwendet wird:

  • Dereferenzieren von rohen Zeigern
  • Aufrufen von Funktionen oder Methoden, die unsafe sind (einschließlich des Aufrufs einer Funktion über FFI, siehe [einem vorherigen Kapitel des Buches])
  • Zugreifen auf oder Ändern von statischen veränderlichen Variablen
  • Implementieren unsicherer Traits

Rohzeiger

Rohzeiger * und Referenzen &T verhalten sich ähnlich, aber Referenzen sind immer sicher, da aufgrund des Borrow-Checkers garantiert ist, dass sie auf gültige Daten verweisen. Das Dereferenzieren eines rohen Zeigers kann nur innerhalb eines unsicheren Blocks erfolgen.

fn main() {
    let raw_p: *const u32 = &10;

    unsafe {
        assert!(*raw_p == 10);
    }
}

Aufrufen unsicherer Funktionen

Einige Funktionen können als unsafe deklariert werden, was bedeutet, dass es die Verantwortung des Programmierers ist, die Korrektheit zu gewährleisten, anstatt des Compilers. Ein Beispiel dafür ist [std::slice::from_raw_parts], das einen Slice erstellt, wenn ein Zeiger auf das erste Element und eine Länge angegeben werden.

use std::slice;

fn main() {
    let some_vector = vec![1, 2, 3, 4];

    let pointer = some_vector.as_ptr();
    let length = some_vector.len();

    unsafe {
        let my_slice: &[u32] = slice::from_raw_parts(pointer, length);

        assert_eq!(some_vector.as_slice(), my_slice);
    }
}

Für slice::from_raw_parts ist eine der Annahmen, die erhalten werden muss, dass der übergebene Zeiger auf gültigen Speicher zeigt und dass der daraufhin angezeigte Speicher vom richtigen Typ ist. Wenn diese Invarianten nicht eingehalten werden, ist das Verhalten des Programms undefiniert und es ist nicht vorhersehbar, was passieren wird.

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Lab zu Unsicheren Operationen abgeschlossen. Sie können in LabEx weitere Labs absolvieren, um Ihre Fähigkeiten zu verbessern.