Rust (Programmiersprache)
Rust | |
---|---|
Basisdaten | |
Paradigmen: | multiparadigmatisch (generisch, nebenläufig, funktional, imperativ, strukturiert) |
Erscheinungsjahr: | 2010; erste stabile Version 2015 |
Designer: | Graydon Hoare |
Entwickler: | Mozilla[1], Graydon Hoare[1][2], Rust-Stiftung[3] |
Aktuelle Version | 1.82.0[4] (17. Oktober 2024) |
Typisierung: | stark, statisch, affin,[5] Typinferenz |
Beeinflusst von: | Alef[6], C++[6], C#[6], Cyclone[6], Erlang[6], Haskell[6], Limbo[6], Newsqueak[6], Objective CAML[6], Ruby[6], Scheme[6], Standard ML[6], Swift[6] |
Betriebssystem: | Linux, macOS, Windows, FreeBSD, Android, iOS[7] und weitere[8][9] |
Lizenz: | Apache-Lizenz, Version 2.0[10][11], MIT-Lizenz[10][11] |
www.rust-lang.org |
Rust ist eine Multiparadigmen-Systemprogrammiersprache, die von der Open-Source-Community entwickelt wird und unter anderem von Mozilla Research gesponsert ist.[12] Sie wird mit dem Ziel entwickelt, sicher, nebenläufig und praxisnah zu sein.[13] Sicherheit bezieht sich dabei insbesondere auf die Vermeidung von Programmfehlern, die zu Speicherzugriffsfehlern oder Pufferüberläufen und damit unter Umständen auch zu Sicherheitslücken führen, vor allem auch in nebenläufigen Prozessen. Im Gegensatz zu anderen Programmiersprachen mit automatischer Speicherverwaltung verwendet Rust hierfür keine Garbage Collection, sondern ein besonderes Typsystem. Dessen Typsicherheit wurde formal bewiesen.[14]
Rust vereint Ansätze aus verschiedenen Programmierparadigmen, unter anderem aus der funktionalen, der objektorientierten und der nebenläufigen Programmierung und erlaubt so ein hohes Abstraktionsniveau. Beispielsweise gibt es in Rust algebraische Datentypen, Pattern Matching, Traits (ähnlich den Typklassen in Haskell), Closures sowie Unterstützung für RAII. Die Sprache wurde so entworfen, dass die Kosten der Abstraktionen zur Laufzeit so gering wie möglich bleiben können (zero-cost abstractions), um eine mit C++ vergleichbare Performanz zu erreichen.[15]
Geschichte
[Bearbeiten | Quelltext bearbeiten]Die Sprache entstand aus einem persönlichen Projekt des Mozilla-Mitarbeiters Graydon Hoare. Mozilla begann das Sponsoring des Projekts im Jahr 2009.[16] Es wurde 2010 zum ersten Mal angekündigt.[17] Im selben Jahr begann der Wechsel von einem (noch in OCaml geschriebenen) ersten Compiler zu einem neuen Compiler, der selbst in Rust geschrieben ist.[18] Dieser rustc genannte Compiler verwendet LLVM als Back-End und kann sich seit 2011 erfolgreich selbst übersetzen.[19] Eine erste stabile Version von Compiler und Standardbibliothek, Rust 1.0, wurde am 15. Mai 2015 veröffentlicht.[20]
Im August 2020 entließ Mozilla im Rahmen einer Unternehmensumstrukturierung unter anderem große Teile des Rust-Teams.[21] Das Servo-Team wurde komplett aufgelöst. Nach Angaben der Vorstandsvorsitzenden Mitchell Baker wurde dies durch die Folgen der COVID-19-Pandemie notwendig.[22][23] Das Ereignis führte zu Bedenken über die Zukunft von Rust.[24]
Daher gründete das Rust-Kernteam eine Rust-Stiftung, um das Eigentum an allen Markenzeichen und Domainnamen zu übernehmen wie auch die finanzielle Verantwortung für deren Kosten.[25]
Am 8. Februar 2021 gaben die Unternehmen AWS, Huawei, Google, Microsoft und Mozilla sowie fünf Mitglieder aus dem Rust-Team die Gründung der Rust Foundation bekannt.[26][27]
Sprachdesign
[Bearbeiten | Quelltext bearbeiten]Syntax, Sprachkonstrukte
[Bearbeiten | Quelltext bearbeiten]Syntaktisch ist die Sprache an C angelehnt. Mehrere aufeinanderfolgende Anweisungen werden durch ein Semikolon getrennt, Blöcke stehen in geschweiften Klammern. In vielen Details weicht die Syntax allerdings davon ab. So werden beispielsweise keine Klammern um die Bedingungen von if
- und while
-Statements benötigt, stattdessen aber geschweifte Klammern um den dahinterstehenden Block erzwungen, auch wenn dort nur eine Anweisung steht. Das Schlüsselwort for
leitet in Rust immer eine Foreach-Schleife ein, die das Iterieren über beliebige (auch benutzerdefinierte) Container und Objekte ermöglicht. Anstelle des switch
-Statements gibt es die wesentlich mächtigeren match
-Ausdrücke, die nicht nur mit Zahlen und Zeichenketten umgehen können, sondern Pattern Matching auf beliebig verschachtelten Strukturen durchführen können.
Variablen werden normalerweise klein (snake_case
) geschrieben, außer wenn es sich um Konstanten handelt. Bei Konstanten schreibt man jeden Buchstaben groß und trennt jedes Wort mit einem Unterstrich (SCREAMING_SNAKE_CASE
).[28] Datentypen mit Ausnahme der primitiven mit großem Anfangsbuchstaben (PascalCase
). Typparameter von generischen Typen und Funktionen stehen in spitzen Klammern. Zwei Doppelpunkte drücken aus, dass der Bezeichner auf der rechten Seite aus dem Namensraum des Bezeichners auf der linken Seite entstammen soll. Die Bindung eines Bezeichners x
an einen Wert wird
let x: Typ = Wert;
geschrieben, wobei die Angabe des Typs auch entfallen darf, wenn der Typ abgeleitet werden kann. Eine Variablen-Deklaration für die Variable v
hat die Form:
let mut v: Typ = Initialwert;
oder allgemeiner:
let mut v: Typ;
v = Wert;
Der Compiler überprüft mittels Datenflussanalyse, ob alle Bindungen und Variablen vor dem Auslesen initialisiert wurden. Verwendung von uninitialisiertem Speicher ist nur über einen speziellen Befehl möglich, welcher zwingend mit unsafe
markiert werden muss.
Typsystem
[Bearbeiten | Quelltext bearbeiten]Benutzerdefinierte Datentypen können entweder als struct
(Struktur wie in C) oder als enum
(tagged-Union) definiert werden. Für beide Arten von Datentypen kann man mittels des impl
-Schlüsselwortes Methoden definieren. Die sonst für objektorientierte Programmierung übliche Vererbung gibt es in Rust allerdings nicht; Polymorphie wird stattdessen durch Traits und generische Programmierung ermöglicht. Ein Trait definiert eine Menge von Funktionen und Methoden, die dann jeweils zusammen von Datentypen implementiert werden und bei Typparametern als Einschränkung für die erlaubten Typen dienen können. Dies wird auch für Operatoren verwendet, sodass beispielsweise der Operator +
mit jedem Datentyp verwendet werden kann, der den Trait Add
implementiert.[29] Alle Funktions-, Methoden- und Operatoraufrufe werden dabei statisch gebunden, wodurch dem Compiler einige Optimierungen ermöglicht werden. Allerdings kann über sogenannte Trait-Objects auch mittels dynamischer Bindung auf Trait-Methoden zugegriffen werden. Es ist erlaubt, sowohl existierende Traits aus fremdem Code für benutzerdefinierte Typen, als auch neue, benutzerdefinierte Traits für existierende Typen zu implementieren.
Zeiger, Speicherverwaltung
[Bearbeiten | Quelltext bearbeiten]Rust kennt neben den sogenannten Raw-Pointern, die Zeigern in C entsprechen und nur in explizit als unsafe
markiertem Code dereferenziert werden dürfen, auch noch Referenzen. Diese zeigen immer auf gültigen Speicher und dürfen niemals den Wert null annehmen. Es werden zwei verschiedene Arten von Referenzen unterschieden: gemeinsame Referenzen (shared references), eingeleitet durch &
, und veränderbare Referenzen (mutable references), eingeleitet durch &mut
. Der Rust-Compiler garantiert statisch, dass keine Referenz das von ihr referenzierte Objekt „überlebt“, dass das referenzierte Objekt nicht verändert wird, während eine Referenz (egal ob gemeinsam oder veränderbar) existiert, und dass eine veränderbare Referenz – wenn eine solche existiert – stets die einzige Referenz auf ein Objekt ist, sodass Veränderungen am Objekt vorgenommen werden können, ohne dabei Referenzen zum selben Objekt an anderen Stellen im Code oder sogar in anderen Threads ungültig zu machen.
Das Erstellen von Referenzen wird auch als Borrowing (Ausleihen) bezeichnet und bildet zusammen mit dem Konzept der Ownership (Besitz) die Grundlage für die sichere Speicherverwaltung ohne Garbage Collection. Ownership bedeutet hier, dass jedes Objekt im Speicher im Besitz derjenigen Variable ist, der es bei der Erstellung zugewiesen wird. Am Ende der Lebensdauer dieser Variable wird der Speicher automatisch freigegeben. Für die meisten komplexeren Datentypen verwendet Rust die sogenannte Move-Semantik, sodass bei Zuweisung eines Objektes zu einer anderen Variablen das Objekt „verschoben“ wird, und ein Zugriff auf die alte Variable daraufhin nicht mehr möglich ist. Auch beim Übergeben von Objekten als Wertparameter an Funktionen (call by value) werden solche Objekte in die Funktion „hineingeschoben“ und sind von außen nicht mehr zugreifbar, wenn sie nicht wieder von der Funktion zurückgegeben werden. Primitive Datentypen im engeren Sinne verwenden keine Move-Semantik, sondern die sonst übliche Copy-Semantik (Zuweisungen erstellen eine Kopie). Dies gilt nicht für folgende Datentypen, die in Rust als primitiv gelten: veränderbare Referenzen (mutable references)[30], manche Closures[31], str[32] und manche Arrays[33] und manche Tupel[34]. Bei benutzerdefinierten Datentypen kann mittels des Copy-Traits selbst entschieden werden, ob Move- oder Copy-Semantik verwendet werden soll.
Zur dynamischen Speicherverwaltung stehen die Smart-Pointer-Typen Box
, Rc
und der Hilfstyp RefCell
zur Verfügung, welche einerseits dem System Ownership-Borrowing-Lifetime-Move unterworfen sind, dieses System andererseits auf die Laufzeitdynamik übertragen. Der Typ Box<T>
beschreibt einen besitzenden Zeiger auf einen Wert vom Typ T
im dynamisch allozierten Speicher. Der Typ Rc<T>
beschreibt über Referenzzählung einen gemeinschaftlichen Besitz auf einen unveränderlichen Wert. Ein unveränderlicher Wert kann jedoch veränderliche innere Daten vom Typ RefCell<T>
besitzen, wobei jeweils ein Referenzzähler für einen Zugriff analog zu &
und &mut
das sichere dynamische Borrowing durch Prüfung zur Laufzeit ermöglicht.
Mit Rc
allein ist keine Dynamik zyklischer Datenstrukturen möglich. Hierzu kann wieder RefCell
herangezogen werden, wobei die Zyklen manuell aufgebrochen werden müssen, damit es nicht zu einem Speicherleck kommt. Als alternatives Konzept ist der Zeigertyp Weak<T>
vorhanden, bei dem die Zeiger analog zu Rc
sind, jedoch keinen Besitz am Wert haben. Zur Umsetzung von Weak
ist in Rc
ein zweiter Referenzzähler implementiert. Ein Zeiger vom Typ Weak
verhindert zwar nicht den Destruktor-Aufruf beim Verschwinden aller Zeiger vom Typ Rc
, die Deallokation des brach liegenden Knotens geschieht dann allerdings erst beim Verschwinden des letzten Zeigers vom Typ Weak
. Die Destruktor-Aufrufe sorgen dabei für ein automatisches Aufbrechen der Zyklen.
Für die nebenläufige Programmierung ist ein Austausch von Rc
gegen Arc
, und RefCell
gegen die analogen Konzepte Mutex
oder RwLock
notwendig.
Nullzeiger kommen in Rust nicht vor. Abwesenheit eines Werts wird stattdessen durch den Typ Option<T>
modelliert, welcher es als enum
ermöglicht, zwischen Some(T)
(Vorhandensein) und None
(Abwesenheit) zu unterscheiden. Die Verwendung von Optionen ist nicht auf Zeiger beschränkt. Möchte man z. B. einen großen Teil einer struct
zunächst uninitialisiert lassen, dann kann man diesen als innere struct
hinter einer Option verbergen und mit None
initialisieren.
Fehlerbehandlung
[Bearbeiten | Quelltext bearbeiten]Rust unterscheidet zwischen nicht behebbaren (unrecoverable) und behebbaren (recoverable) Fehlern. Tritt ein nicht behebbarer Fehler auf, wird eine Meldung ausgegeben, der Stack aufgeräumt (unwinding) und der betroffene Thread beendet. Wenn dies nicht der Haupt-Thread ist, läuft das Programm weiter. Ein sofortiger Programmabbruch via abort()
ist auch konfigurierbar. Für behebbare Fehler gibt es in Rust die in vielen Sprachen vorhandene Ausnahmebehandlung mit automatischem Stack-Unwinding nicht. Stattdessen werden behebbare Fehler als gewöhnliche Rückgabewerte von Funktionen modelliert. Zur strengen Typisierung dienen dabei die Typen Result<T,E>
und Option<T>
. Beide Typen sind als enum
formuliert, Result
unterscheidet hierbei zwischen Ok(T)
(normale Werte) und Err(E)
(Fehlerwerte), Option
definiert hingegen Some(T)
(normale Werte) und None
(kein Wert).[35]
Ein Laufzeitnachteil entsteht bei der Rückgabe von enum
bzw. struct
in vielen Fällen nicht, da der Compiler in der Lage ist, für größere Objekte automatisch Zeiger zu erzeugen und Nullzeiger-Optimierungen durchzuführen.
Beispiele
[Bearbeiten | Quelltext bearbeiten]Hello-World-Funktion
[Bearbeiten | Quelltext bearbeiten]fn main() {
println!("Hello, world!");
}
Das obige Beispiel gibt den Text Hello, world!
am Ausgabemedium aus. println!()
ist hierbei keine gewöhnliche Funktion, sondern ein Makro. Die Funktionsdeklaration erfolgt in Rust mit dem Schlüsselwort fn
.
Fakultäts-Funktion
[Bearbeiten | Quelltext bearbeiten]Für die Berechnung der Fakultät einer Zahl , also , existieren verschiedene Lösungswege, insbesondere ein rekursiver und ein iterativer. Beide sind in Rust umsetzbar.
Iterativ
[Bearbeiten | Quelltext bearbeiten]fn fakultaet(i: u64) -> u64 {
let mut acc = 1;
for num in 2..=i {
acc *= num;
}
acc
}
Da die Fakultät für alle natürlichen Zahlen definiert ist, kann als Datentyp auf u64
, eine vorzeichenlose 64-Bit-Ganzzahl,[36] zurückgegriffen werden. In dieser Variante wird die Fakultät nach obiger Definition umgesetzt. Auffällig ist das Schlüsselwort mut
in Zeile 2, das in der Deklaration der Variable acc vorkommt, um diese als veränderlich (mutable) zu kennzeichnen, da im Schleifenkörper in Zeile 4 eine erneute Wertzuweisung vorgenommen wird. Eine explizite return
-Anweisung wird in Rust nicht benötigt, weil der letzte Ausdruck (der aufgrund des fehlenden Semikolons keine Anweisung ist) als Rückgabewert gilt.[37] Dieser Ausdruck muss dem Rückgabetypen aus dem Funktionskopf entsprechen.
Alternativ erlaubt es Rust, das Problem im Sinne der funktionalen Programmierung anzugehen. Sogenannte Iterators bieten eine Möglichkeit, iterierbare Objekte zu verarbeiten. So lässt sich die Fakultät mit Hilfe des Iterators (1..=i)
und dessen Methode product()
[38] wie folgt darstellen:
fn fakultaet(i: u64) -> u64 {
(1..=i).product()
}
Rekursiv
[Bearbeiten | Quelltext bearbeiten]fn fakultaet(i: u64) -> u64 {
match i {
0 => 1,
n => n * fakultaet(n - 1)
}
}
Bei dieser Variante liegt der Kern in einer Fallunterscheidung, mit der die Fakultät ebenfalls definiert werden kann:
Dieser Ausdruck lässt sich in Rust mittels Pattern Matching und rekursivem Funktionsaufruf implementieren.
Behandlung von Überlauf
[Bearbeiten | Quelltext bearbeiten]Mit dem hier benutzten 64-Bit-Integer-Datentyp lässt sich die Fakultät nur bis 20 berechnen, bis ein Überlauf passiert, welcher nur noch falsche Ergebnisse liefert. Dies geschieht häufig unbemerkt. Je nach Kompiliermethode würde dieser Überlauf in den obigen Beispielen als nicht behebbarer Fehler bemerkt, sodass das Programm sich beendet, oder es würde mit dem Überlauf weitergerechnet.
Stattdessen kann dieser Fehlerfall wie folgt mit Hilfe des Typsystems behandelt werden:
fn fakultaet(i: u64) -> Option<u64> {
match i {
0 => Some(1),
n => match fakultaet(n - 1) {
Some(m) => n.checked_mul(m),
None => None
}
}
}
Stapelspeicher
[Bearbeiten | Quelltext bearbeiten]Die kombinierte Nutzung von Enumerationen, Strukturen und Zeigern erlaubt die Konstruktion komplexer Datenstrukturen. Das folgende Beispiel zeigt die Implementierung eines unbeschränkten Stapelspeichers als einfach verkettete Liste, der durch Verhüllung in ein Modul zu einem abstrakten Datentyp gemacht wird. Die öffentliche Schnittstelle ist durch das Schlüsselwort pub
gekennzeichnet.
Die Formulierung des abstrakten Datentyps Stack<T>
ist generisch über seinem Elementtyp T
gestaltet. Man sagt auch, Stack<T>
ist parametrisch polymorph oder ist allquantifiziert über die Typvariable T
. Bei der Erzeugung von Maschinencode stehen dem Compiler nun zwei Möglichkeiten zur Wahl. Entweder die Funktionalität wird für jeden Elementtyp neu generiert, ein Monomorphisierung genannter Prozess, oder aber eine Laufzeit-polymorphe Schnittstelle wird generiert, die einen beliebigen Elementtyp über eine Dispatch-Tabelle verarbeiten kann. Der aktuelle Compiler ist nur zu Ersterem fähig, welches den Vorteil der höheren Optimierbarkeit bietet.
mod stack {
struct Node<T> {
data: T,
next: Option<Box<Node<T>>>
}
pub struct Stack<T> {
top: Option<Box<Node<T>>>
}
impl<T> Stack<T> {
pub fn new() -> Self {
Self{top: None}
}
pub fn push(&mut self, element: T) {
let node = self.top.take();
self.top = Some(Box::new(Node{data: element, next: node}));
}
pub fn pop(&mut self) -> Option<T> {
if let Some(node) = self.top.take() {
self.top = node.next;
Some(node.data)
} else {
None
}
}
}
}
use stack::Stack;
fn main() {
let mut a: Stack<i32> = Stack::new();
a.push(1);
a.push(2);
println!("{:?}", a.pop());
println!("{:?}", a.pop());
println!("{:?}", a.pop());
}
Die Notation &mut self
ist eine Kurzschreibweise für self: &mut Self
.
Eine Problemsituation tut sich bei der Entnahme des Knotens aus top
auf. Weil es hier zur Besitzübertragung an node
kommt, würde die Speicherzelle ungültig werden. Zur Umgehung dieser gefährlichen Situation wurde die Methode Option::take
genutzt, die die ungültige Speicherzelle sogleich mit dem Wert None
überschreibt.
Die Standardbibliothek enthält viele Hilfsfunktionen, von denen einige manchmal sogar lediglich zur moderaten Verknappung von Quelltext herangezogen werden. Benutzung der monadischen Methode Option::map
gestattet bspw. eine kürzere Formulierung der Methode pop
:
pub fn pop(&mut self) -> Option<T> {
self.top.take().map(|node| {
self.top = node.next;
node.data
})
}
Es ist im Allgemeinen nicht empfehlenswert, grundlegende Datenstrukturen neu zu erfinden, da dies eine vermeidbare Fehlerquelle ist und den Datenaustausch verkomplizieren kann. Anstelle des hier beispielhaft gezeigten Stack sollte Vec verwendet werden.[39]
Verwendung
[Bearbeiten | Quelltext bearbeiten]Der Rust-Compiler wird standardmäßig mit Cargo, einer Paketverwaltung für Rust-Software, ausgeliefert, die verwendete Bibliotheken automatisch herunterlädt und Abhängigkeiten auflöst. Jedes Paket beinhaltet eine Konfigurationsdatei im TOML-Format, die als Cargo.toml im Paketverzeichnis abgelegt wird. In dieser werden neben allgemeinen Informationen zum Paket (u. a. Name, Version und Autoren) auch die benötigten Abhängigkeiten angegeben.[40]
Eine Vielzahl wiederverwendbarer Open-Source-Komponenten stehen im offiziellen Paket-Repository crates.io[41] zur Verfügung. Ab der Version 1.34.0 ist es zudem möglich, andere Paket-Repositories zu nutzen. Dies ermöglicht beispielsweise, dass Unternehmen eigene, interne Paket-Repositories erstellen und für Closed-Source-Komponenten nutzen.
Rust findet unter anderem in folgenden Projekten Verwendung:
- Mozilla Firefox[42][43]
- Mozilla Thunderbird – ab Version 128, für mehr Performance und Sicherheit, aber auch um zukünftig Code zwischen Desktop und Mobile gleichermaßen entwickeln und teilen zu können.[44]
- Servo – eine neue Layout-Engine für Webbrowser von Mozilla.[45]
- OpenDNS – verwendet Rust in zwei Softwarekomponenten.[46][47]
- librsvg – freie SVG-Bibliothek, Teil des Gnome-Projektes.
- Google Fuchsia – ein Betriebssystem, das von Google entwickelt wird.[48]
- Deno – eine Laufzeitumgebung für JavaScript und TypeScript als Alternative zu Node.js
- RustDesk – eine Remote-Desktop-Anwendung
- Signal Messenger – Kernfunktionalitäten wie Signal-Protokoll oder Kryptographie für alle Apps (Android, iOS, Desktop).[49]
Betriebssysteme
[Bearbeiten | Quelltext bearbeiten]Rust findet in vielen Betriebssystemen zunehmend Anwendung, da vor allem Speicherzugriffsfehler oder Pufferüberläufe immer wieder zu Sicherheitslücken führen, welche mit Rust von Haus aus vermieden werden können. Dabei wird zumeist C oder C++ ersetzt.
Microsoft Windows
[Bearbeiten | Quelltext bearbeiten]Microsoft ist Gründungsmitglied der Rust Foundation und bezahlt als Platinum-Sponsor 300.000 US-Dollar im Jahr an die Organisation.[50]
2020 hatte Microsoft angekündigt, Teile von Windows in Rust neu zu schreiben. DWriteCore, eine Engine zur Textanalyse, Layout und Rendering, besteht mittlerweile aus rund 150.000 Zeilen Rust.[51] „Auch wenn es sich um einen kleinen Test handelt, werden wir die Nutzung von Rust im Kernel weiter steigern“, heißt es in einem Windows Blog Post vom Juli 2023, zur Implementierung der GDI-Region in win32kbase_rs.sys in sicherem Rust.[52] Bereits im Oktober 2023 war Rust im Kernel von Windows 11, als ein SysCall, angekommen.[53]
Im November 2023 hat der bei Microsoft für Betriebssystemsicherheit zuständige David Weston angegeben, dass Rust von Microsofts hauseigenen Entwicklungswerkzeugen künftig „erstklassig“ unterstützt werden und damit auf einer Stufe wie C oder C++ stehen soll. Dies bedeutet vor allem Arbeiten an sowie Investitionen in interne Systeme. Dafür sind 10 Millionen US-Dollar veranschlagt. Als Ziel möchte man vor allem die Speichersicherheit der eigenen Anwendungen erhöhen. Zusätzlich zu der Ankündigung hat man neben dem Mitgliedsbeitrag eine Million an die Rust Foundation gespendet.[54]
Google Android
[Bearbeiten | Quelltext bearbeiten]Google ist Gründungsmitglied der Rust Foundation und zahlt als Platinum-Sponsor 300.000 US-Dollar im Jahr an die Organisation.[50]
Bereits seit 2019 wird Rust von Google in Android verwendet, was laut Aussage von Android-Sicherheits-Ingenieur Jeffrey Vander Stoep von 2019 bis 2022 bereits die Anzahl der Speichersicherheitsfehler von 223 auf 85 pro Jahr reduzieren konnte. Bisher wurden auch keine Speicherfehler im hinzugefügten Rust-Code gefunden.[55]
In Android 12 wurde Rust-Support erstmals angekündigt. In Android 13 war bereits ein größerer Teil des neu hinzugefügten Code in Rust geschrieben.[55]
Für Android 14 wurde bereits eine Bare-Metal-Rust-Umsetzung veröffentlicht. Die Protected-Virtual-Machine-Firmware ersetzt den in C geschriebenen Open-Source-Bootloader U-Boot. Grund dafür sind Speicherfehler wie Pufferüberlauf oder Out-of-Bounds-Fehler im Bootloader, die aufgrund der Angreifbarkeit eines Bootloaders zumeist als kritisch eingestuft werden und zukünftig damit vermieden werden könnten.[56]
Im November 2023 wurde der erste komplette Linux-Treiber für Android namens Binder erstellt. Dabei handelt es sich um eine komplett neue Umsetzung der Interprozesskommunikation (IPC), zuvor in C umgesetzt, und im Zuge dessen wurden auch weitere Pläne und Funktionen umgesetzt.[57]
Linux Kernel
[Bearbeiten | Quelltext bearbeiten]Mit dem Linux-Kernel 6.1 wurde erstmals die Möglichkeit geschaffen, neben der Programmiersprache C auch Rust als zweite Programmiersprache im Kernel zu verwenden. Dies war aber noch nicht als produktiv zu bezeichnen, da noch entsprechende Rust-Module im Kernel fehlten.[58][59]
Erst mit den folgenden Kerneln wurden Module und mehrere Updates der Toolchain gemacht, um dem produktiven Einsatz näher zu kommen und zukünftig näher an der aktuellen Entwicklung von Rust zu sein.[60][61]
In einem Interview mit Rust-für-Linux-Betreuer Miguel Ojeda wird berichtet, dass rund 70 % der Sicherheitslücken auf Speichersicherheitsprobleme der C/C++-Codebasis zurückzuführen sind, die sich zukünftig mit Rust vermeiden ließen. Für Entwickler bietet Rust als Sprache, Bibliothek und Tooling viele moderne Verbesserungen im Vergleich zu C.[62]
Literatur
[Bearbeiten | Quelltext bearbeiten]- Georg Nold: Neuling im Programmiersprachenwald. Was Rust hat, das andere nicht haben. In: iX – Magazin für professionelle Informationstechnik. Nr. 5, Mai 2021, ISSN 0935-9680, S. 42–44.
Weblinks
[Bearbeiten | Quelltext bearbeiten]- Offizielle Website
- Offizielles Lehrbuch (englisch) / Deutsche Übersetzung
- Offizielle Syntaxreferenz
- Introduction – Rust By Example. In: rustbyexample.com. (englisch).
Einzelnachweise
[Bearbeiten | Quelltext bearbeiten]- ↑ a b prev.rust-lang.org. (abgerufen am 24. Februar 2019).
- ↑ jaxenter.com. (abgerufen am 31. Januar 2018).
- ↑ foundation.rust-lang.org.
- ↑ Announcing Rust 1.82.0. 17. Oktober 2024 (englisch, abgerufen am 17. Oktober 2024).
- ↑ Alexis Beingessner: The Pain Of Real Linear Types in Rust. In Beingessners Blog, 8. Mai 2017, abgerufen am 10. Oktober 2019.
- ↑ a b c d e f g h i j k l m In: Influences - The Rust Reference.
- ↑ Doc building for ios. In: GitHub. Abgerufen am 4. Januar 2015.
- ↑ Rust Platform Support. In: Rust Forge. Abgerufen am 3. Juni 2019 (englisch).
- ↑ Frequently Asked Questions. In: Rust Embedded. Abgerufen am 3. Juni 2019 (englisch).
- ↑ a b In: GitHub.
- ↑ a b github.com.
- ↑ Rust. Mozilla Research, abgerufen am 3. Mai 2019.
- ↑ The Rust Programming Language. Abgerufen am 21. Oktober 2012.
- ↑ Ralf Jung: Understanding and Evolving the Rust Programming Language. Abgerufen am 15. Juli 2021.
- ↑ The Rust Project Developers: The Rust Language FAQ: How fast is Rust? Abgerufen am 27. Juni 2021 (englisch).
- ↑ Project FAQ. 14. September 2010, abgerufen am 11. Januar 2012.
- ↑ Future Tense. 29. April 2011, abgerufen am 6. Februar 2012: „At Mozilla Summit 2010, we launched Rust, a new programming language motivated by safety and concurrency for parallel hardware, the “manycore” future which is upon us.“
- ↑ Graydon Hoare: Rust Progress. In: Graydon’s work on Mozilla. 2. Oktober 2010, archiviert vom am 19. März 2012; abgerufen am 3. April 2016 (englisch).
- ↑ Graydon Hoare: [rust-dev] stage1/rustc builds. 20. April 2011, abgerufen am 20. April 2011: „After that last change fixing the logging scope context bug, looks like stage1/rustc builds. Just shy of midnight :)“
- ↑ Announcing Rust 1.0
- ↑ Mozilla streicht Stellen und Projekte. heise online, 29. August 2020, abgerufen am 9. Februar 2021.
- ↑ @tschneidereit: "Much of the team I used to manage was part of the Mozilla layoffs on Tuesday. That team was Mozilla's Rust team, and Mozilla's Wasmtime team. I thought I'd know how to talk about it by now, but I don't. It's heartbreaking, incomprehensible, and staggering in its impact". In: Twitter. 12. August 2020, abgerufen am 9. Februar 2021 (englisch).
- ↑ @asajeffrey: "Mozilla is closing down the team I'm on, so I am one of the many folks now wondering what the next gig will be. It's been a wild ride!" In: Twitter. 11. August 2020, abgerufen am 9. Februar 2021 (englisch).
- ↑ Is Rust in Trouble After Big Mozilla Layoffs? In: Dice. 27. August 2020, abgerufen am 9. Februar 2021 (englisch).
- ↑ Laying the foundation for Rust's future. In: Rust Blog. 18. August 2020, abgerufen am 9. Februar 2021 (englisch).
- ↑ Hello World! In: Rust Blog. Rust Foundation, 8. Februar 2021, abgerufen am 9. Februar 2021 (englisch).
- ↑ Silke Hahn: Willkommen, Rust Foundation! Die Programmiersprache hat eine neue Heimat. In: heise online. 8. Februar 2021, abgerufen am 9. Februar 2021.
- ↑ 0430-finalizing-naming-conventions - The Rust RFC Book. 2. November 2014, abgerufen am 8. September 2024.
- ↑ Dokumentation des „Add“-Traits
- ↑ Trait-Implementierungen für Referenzen. In: Dokumentation der Rust-Standardbibliothek. Abgerufen am 7. August 2023 (englisch).
- ↑ Der „Copy“-Trait. In: Dokumentation der Rust-Standardbibliothek. Abgerufen am 7. August 2023 (englisch).
- ↑ Der „str“-Datentyp. In: Dokumentation der Rust-Standardbibliothek. Abgerufen am 7. August 2023.
- ↑ Der „array“-Datentyp. In: Dokumentation der Rust-Standardbibliothek. Abgerufen am 7. August 2023 (englisch).
- ↑ Der „tuple“-Datentyp. In: Dokumentation der Rust-Standardbibliothek. Abgerufen am 7. August 2023 (englisch).
- ↑ Recoverable Errors with Result – The Rust Programming Language. Abgerufen am 23. April 2019.
- ↑ u64 – Rust. Abgerufen am 21. April 2019.
- ↑ Functions – Rust By Example. Abgerufen am 21. April 2019.
- ↑ std::iter::Product – Rust Documentation. Abgerufen am 21. April 2019.
- ↑ std::collections. In: Rust documentation. Abgerufen am 13. Oktober 2020.
- ↑ The Manifest Format – The Cargo Book. Abgerufen am 19. April 2019.
- ↑ The Rust community’s crate host. Abgerufen am 3. April 2017 (englisch).
- ↑ Dave Herman: Shipping Rust in Firefox. In: Mozilla Hacks. 12. Juli 2016, abgerufen am 2. April 2017 (englisch).
- ↑ Quantum. In: Mozilla Wiki. Abgerufen am 3. April 2017 (englisch).
- ↑ Jason Evangelho: Welcome to Thunderbird 128 "Nebula". 12. Juli 2024, abgerufen am 22. Juli 2024 (amerikanisches Englisch).
- ↑ Rainald Menge-Sonnentag: Mozilla veröffentlicht erste Preview der neuen Browser-Engine Servo. In: Heise Newsticker. 4. Juli 2016, abgerufen am 4. Juli 2016.
- ↑ Denis Frank: Using HyperLogLog to Detect Malware Faster Than Ever. In: OpenDNS Security Labs. Archiviert vom am 3. Juni 2016; abgerufen am 19. März 2016.
- ↑ Frank Denis: ZeroMQ: Helping us Block Malicious Domains in Real Time. In: OpenDNS Security Labs. Archiviert vom am 30. Juni 2016; abgerufen am 19. März 2016.
- ↑ Fuchsia – Rust. In: fuchsia.googlesource.com. Abgerufen am 5. März 2019.
- ↑ Overview. Signal, 26. März 2023, abgerufen am 27. März 2023 (englisch).
- ↑ a b Rust Foundation. In: foundation.rust-lang.org. Abgerufen am 7. November 2023 (englisch).
- ↑ Thomas Claburn: Microsoft is rewriting core Windows libraries in Rust. In: The Register. 27. April 2023, abgerufen am 7. Juni 2023 (englisch).
- ↑ Amanda Langowski, Brandon LeBlanc: Announcing Windows 11 Insider Preview Build 25905. In: blogs.windows.com. 12. Juli 2023, abgerufen am 5. November 2023 (amerikanisches Englisch).
- ↑ Rust is now up and running in Windows 11 kernel. In: windowsreport.com. 11. Mai 2023, abgerufen am 4. November 2023 (amerikanisches Englisch).
- ↑ Golem.de: IT-News für Profis. In: golem.de. Abgerufen am 7. November 2023.
- ↑ a b Memory Safe Languages in Android 13. In: Google Online Security Blog. Abgerufen am 4. November 2023 (englisch).
- ↑ heise online: Weniger Speicherfehler: Google setzt für Android nun auch auf Bare-Metal Rust. 11. Oktober 2023, abgerufen am 4. November 2023.
- ↑ Android: Google zeigt ersten Linux-Treiber in Rust. Abgerufen am 4. November 2023.
- ↑ heise online: Linux 6.1 als nächster Langzeit-Kernel erschienen. 13. Dezember 2022, abgerufen am 4. November 2023.
- ↑ Ferdinand Thommes: Linux 6.1 mit initialem Rust-Code freigegeben. 12. Dezember 2022, abgerufen am 10. Mai 2023.
- ↑ Linux 6.5 Upgrading The Rust Toolchain, New Modules Added. Abgerufen am 4. November 2023 (englisch).
- ↑ Rust WQ Abstractions, Rust Toolchain Upgrade & Android Kernel Builds For Linux 6.7. Abgerufen am 4. November 2023 (englisch).
- ↑ heise online: Drei Fragen und Antworten: Was die Rust-Zukunft für Linux bringt. 6. März 2023, abgerufen am 4. November 2023.