0Pricing
Learn Rust Coding · Leçon

Interagir avec Rust non sûr

Comprenez quand et comment utiliser les blocs `unsafe` pour contourner les vérifications de sûreté de Rust et permettre la FFI ainsi que les opérations mémoire de bas niveau.

Interagir avec Rust non sûr est une leçon Learn Rust Coding gratuite sur CoddyKit. Ceci est la leçon 3 sur 3. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Learn Rust Coding, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Learn Rust Coding comprend 3 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

Unsafe Rust: An Introduction

Welcome to Unsafe Rust! While Rust is famous for its memory safety guarantees, there are specific scenarios where you might need to bypass some of these checks.

The unsafe keyword in Rust allows you to do just that. It's not a way to write 'bad' code, but rather a tool for advanced use cases where you need more direct control over memory or hardware.

The Five Unsafe Superpowers

When you use an unsafe block, you gain access to five special actions that the Rust compiler normally prevents:

  • Dereference raw pointers: Directly access memory addresses.
  • Call unsafe functions or methods: Execute functions with preconditions the compiler can't verify.
  • Implement unsafe traits: Declare that your type upholds specific invariants.
  • Access or modify mutable static variables: Share mutable state globally, risking data races.
  • Access fields of unions: Read from a union, which might be an invalid type for the current data.

Dereferencing Raw Pointers

Raw pointers are memory addresses without Rust's usual safety guarantees. You can create them from references (&T, &mut T) but dereferencing them requires an unsafe block.

This means you, the programmer, are responsible for ensuring the pointer is valid and points to allocated memory.

fn main() {
  let mut num = 5;
  let r1 = &num as *const i32; // Immutable raw pointer
  let r2 = &mut num as *mut i32; // Mutable raw pointer

  unsafe { // The `unsafe` block starts here
    println!("r1 points to: {}", *r1);
    *r2 = 10; // Modify data through mutable raw pointer
    println!("r2 points to: {}", *r2);
  } // The `unsafe` block ends here

  println!("Num is now: {}", num);
}

Calling Unsafe Functions

Some functions are marked as unsafe fn. This means the function has preconditions that the Rust compiler cannot guarantee. For instance, a function might expect a valid memory address, but cannot verify it.

Calling such functions must be wrapped in an unsafe block, indicating that you, the caller, ensure all preconditions are met.

unsafe fn dangerous_operation() {
  println!("This operation could be dangerous if preconditions aren't met!");
}

fn main() {
  println!("Attempting a dangerous operation...");
  unsafe { // Calling an unsafe function requires `unsafe`
    dangerous_operation();
  }
  println!("Operation completed.");
}

Mutable Static Variables

Rust prevents global mutable state by default to avoid data races. However, you can declare mutable static variables using static mut.

Accessing or modifying these variables is considered unsafe because multiple threads could try to access them simultaneously, leading to undefined behavior. Proper synchronization is your responsibility.

static mut COUNTER: i32 = 0; // A mutable static variable

fn add_to_counter(inc: i32) {
  unsafe { // Modifying `static mut` requires `unsafe`
    COUNTER += inc;
  }
}

fn main() {
  add_to_counter(5);
  unsafe { // Reading `static mut` also requires `unsafe`
    println!("COUNTER after first add: {}", COUNTER);
  }

  add_to_counter(10);
  unsafe {
    println!("COUNTER after second add: {}", COUNTER);
  }
}

Implementing Unsafe Traits

Some traits in Rust are marked as unsafe trait. This signifies that implementing them requires upholding certain invariants that the compiler cannot check.

A common example is the Send and Sync traits, which relate to thread safety. If you manually implement an unsafe trait, you must use unsafe impl Trait for Type and guarantee its safety properties.

For most beginners, you'll encounter this less frequently, as Rust often handles these automatically or via safe abstractions.

Accessing Union Fields

A union is a special type that can hold a value of *one* of its variants at any given time, but all variants share the same memory location. It's similar to C unions.

Accessing a field of a union requires an unsafe block because the compiler cannot know which field is currently active. Reading from an inactive field can lead to undefined behavior or misinterpretation of data.

union Data {
  integer: u32,
  float: f32,
}

fn main() {
  let mut d = Data { integer: 42 }; // Initialize with an integer

  unsafe {
    // Accessing 'integer' is safe here
    println!("Integer value: {}", d.integer);

    // Accessing 'float' is unsafe, as 'integer' was initialized.
    // This would interpret the integer's bits as a float.
    // println!("Float value (unsafe): {}", d.float);
  }

  d.float = 3.14; // Now initialize with a float
  unsafe {
    // Accessing 'float' is safe now
    println!("Float value: {}", d.float);
  }
}

Practical Unsafe Scenarios

While unsafe should be used sparingly, it's crucial for several advanced programming tasks:

  • Foreign Function Interface (FFI): Interacting with code written in other languages (like C/C++ libraries).
  • Performance Optimizations: Sometimes, bypassing Rust's checks can yield small performance gains in critical sections (but measure first!).
  • Low-level System Programming: Writing operating systems, device drivers, or embedded systems.
  • Building Safe Abstractions: Implementing safe data structures or APIs on top of unsafe primitives (e.g., how Vec is built).

Your Responsibility with Unsafe

When you use unsafe, you take on the responsibility of upholding Rust's safety guarantees manually. This means:

  • Ensuring memory is valid and correctly aligned.
  • Preventing data races when dealing with shared mutable state.
  • Avoiding dangling pointers or use-after-free errors.
  • Ensuring all function preconditions are met.

Misusing unsafe can lead to undefined behavior, which is the worst kind of bug and can be very hard to debug.

Unsafe Knowledge Check

Which of the following actions requires an unsafe block in Rust?

Recap: Unsafe Rust

You've learned about Unsafe Rust, a powerful feature that allows you to bypass some of Rust's compile-time safety checks for specific, advanced scenarios.

Remember that unsafe doesn't turn off the borrow checker completely, but it shifts the responsibility for memory safety and invariants entirely to you, the programmer. Use it judiciously and with extreme caution, typically for FFI, low-level optimizations, or building safe abstractions.

Questions Fréquemment Posées

La leçon « Interagir avec Rust non sûr » est-elle gratuite ?

Oui — le texte complet de « Interagir avec Rust non sûr » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Learn Rust Coding, passe à CoddyKit PRO. Le cours Learn Rust Coding comprend 3 leçons au total.

Qu'est-ce que j'apprendrai dans « Interagir avec Rust non sûr » ?

Comprenez quand et comment utiliser les blocs `unsafe` pour contourner les vérifications de sûreté de Rust et permettre la FFI ainsi que les opérations mémoire de bas niveau. Tu pratiques Learn Rust Coding avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Learn Rust Coding ?

Aucune expérience préalable n'est requise. Learn Rust Coding sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 3.

Combien de temps prend la leçon « Interagir avec Rust non sûr » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Learn Rust Coding ?

Oui. Chaque leçon Learn Rust Coding inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Macros déclaratives (`macro_rules!`)
  2. Macros procédurales : Derive, Function
  3. Interagir avec Rust non sûr
← Retour à Learn Rust Coding