---
title: "Partie 3 : Rust: Memory safety sans garabe collector"
description: "Rust a des performances équivalentes à C/C++ avec en plus la sécurité mémoire vérifée dès la compilation. Cela grâce à deux mécanismes: borrowing et ownership."
url: "https://mayorana.ch/fr/blog/why-rust-memory-safe-fr"
language: "fr"
date: "2025-08-09"
author: "Mohamed Bennekrouf"
tags:
  - "rust"
  - "ownership"
  - "memory-safety"
  - "systems-programming"
en_version: "https://mayorana.ch/en/blog/why-rust-memory-safe.md"
---

# Partie 3 : Rust: Memory safety sans garabe collector

Rust n'a pas de GC. Il n'en a pas besoin.

```rust
let msg = String::from("hello");
```

L’allocation mémoire est gérée automatiquement — mais pas par un [garbage collector](https://mayorana.ch/fr/blog/why-garbage-collector-fr).
Grâce au système d’[ownership](https://mayorana.ch/fr/blog/memory-safety-rust), Rust vérifie à la compilation que chaque valeur a un seul propriétaire, et que la mémoire est libérée au bon moment.
Zéro coût. Zéro surprise. Zéro fuite.

## La révolution « ownership »
### Gestion automatique de la mémoire
```rust
fn greet() {
    let s = String::from("hello");
    // Utiliser s...
} // s est dropped ici automatiquement - pas besoin de free() manuel
```

**Ce qui se passe :**
1. Mémoire allouée quand `s` est créé
2. Mémoire automatiquement libérée quand `s` sort du scope
3. **Pas de thread GC qui tourne en background**
4. **Pas d'overhead runtime**

### Fini les Use-After-Free
```rust,compile_fail
fn main() {
    let r;
    {
        let s = String::from("hello");
        r = &s;  // Borrow s
    } // s sort du scope ici
    
    println!("{}", r); // ❌ Erreur de compilation: s doesn't live long enough
}
```

**Message du compilateur :**
```
error[E0597]: `s` does not live long enough
  --> src/main.rs:5:13
   |
5  |         r = &s;
   |             ^^ borrowed value does not live long enough
6  |     }
   |     - `s` dropped here while still borrowed
```

Le bug est **detecté au moment de la compilation**, pas au runtime.

## Borrowing: manipulation de référence sans danger

### Immutable Borrowing
```rust
fn calculate_length(s: &String) -> usize {
    s.len()  // Peut lire s, mais pas le modifier
} // s sort du scope, mais ne drop pas le String (c'est juste une reference)

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);  // Passer une reference
    println!("Length of '{}' is {}.", s1, len);  // s1 encore valide
}
```

### Le mutable borrowing est soumis à certaines règles
```rust
fn main() {
    let mut s = String::from("hello");
    
    let r1 = &mut s;  // Mutable borrow
    // let r2 = &mut s;  // ❌ Cannot have two mutable borrows
    // let r3 = &s;      // ❌ Cannot have immutable borrow while mutable exists
    
    r1.push_str(", world");
    println!("{}", r1);
}
```

**Les règles de borrowing préviennent :**
- [Data races](https://mayorana.ch/fr/blog/ownership-safety-rust-fr) au moment de la compilation
- [Dangling pointers](https://mayorana.ch/fr/blog/dangling-pointer-rust-fr)
- Iterator invalidation
- Problèmes de thread safety

<div class="svg-container" style="margin:2rem 0;">
<svg class="wr3b-fig" viewBox="0 0 800 240" width="100%" style="height:auto;max-width:780px;display:block;margin:0 auto;" role="img" aria-label="Un nombre quelconque de références partagées est autorisé, ou exactement une référence mutable, mais mélanger une mutable et une partagée est rejeté à la compilation">
<!-- style -->
<style>
.wr3b-fig{--bg:#f8fafc;--box:#ffffff;--tx:#1e293b;--mut:#64748b;--ln:#cbd5e1;--ac:#FF6B00;--bad:#e11d48}
:root.dark .wr3b-fig,[data-theme="dark"] .wr3b-fig{--bg:#0f172a;--box:#1e293b;--tx:#f8fafc;--mut:#94a3b8;--ln:#475569}
.wr3b-fig .panel{fill:none;stroke:var(--ln);stroke-width:1.5}
.wr3b-fig .box{fill:var(--box);stroke:var(--ln);stroke-width:1.5}
.wr3b-fig .boxac{fill:var(--box);stroke:var(--ac);stroke-width:2}
.wr3b-fig .boxbad{fill:var(--box);stroke:var(--bad);stroke-width:2;stroke-dasharray:4 3}
.wr3b-fig .ti{fill:var(--tx);font:700 13px ui-sans-serif,system-ui,sans-serif;text-anchor:middle}
.wr3b-fig .tx{fill:var(--tx);font:600 12px ui-sans-serif,system-ui,sans-serif;text-anchor:middle}
.wr3b-fig .mut{fill:var(--mut);font:11px ui-sans-serif,system-ui,sans-serif;text-anchor:middle}
.wr3b-fig .bad{fill:var(--bad);font:700 12px ui-sans-serif,system-ui,sans-serif;text-anchor:middle}
.wr3b-fig .ln{stroke:var(--ln);stroke-width:1.5;fill:none}
.wr3b-fig .lnbad{stroke:var(--bad);stroke-width:1.5;fill:none;stroke-dasharray:4 3}
</style>
<!-- defs -->
<defs>
<marker id="wr3b-arrow-fr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0L10,5L0,10z" fill="var(--ln)"/></marker>
<marker id="wr3b-arrowbad-fr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0L10,5L0,10z" fill="var(--bad)"/></marker>
</defs>
<!-- panel 1: many readers -->
<rect x="25" y="40" width="235" height="145" rx="8" class="panel"/>
<text x="142" y="62" class="ti">Plusieurs lecteurs — OK</text>
<rect x="40" y="76" width="60" height="26" rx="4" class="box"/>
<text x="70" y="94" class="tx">&amp;s</text>
<rect x="112" y="76" width="60" height="26" rx="4" class="box"/>
<text x="142" y="94" class="tx">&amp;s</text>
<rect x="184" y="76" width="60" height="26" rx="4" class="box"/>
<text x="214" y="94" class="tx">&amp;s</text>
<path d="M70,102 L70,112 L142,112" class="ln"/>
<path d="M142,102 L142,112" class="ln"/>
<path d="M214,102 L214,112 L142,112" class="ln"/>
<path d="M142,112 L142,120" class="ln" marker-end="url(#wr3b-arrow-fr)"/>
<rect x="72" y="120" width="140" height="30" rx="5" class="box"/>
<text x="142" y="140" class="tx">String</text>
<text x="142" y="172" class="mut">personne ne peut la modifier</text>
<!-- panel 2: one writer -->
<rect x="282" y="40" width="235" height="145" rx="8" class="panel"/>
<text x="399" y="62" class="ti">Un seul écrivain — OK</text>
<rect x="354" y="76" width="90" height="26" rx="4" class="boxac"/>
<text x="399" y="94" class="tx">&amp;mut s</text>
<path d="M399,102 L399,120" class="ln" marker-end="url(#wr3b-arrow-fr)"/>
<rect x="329" y="120" width="140" height="30" rx="5" class="box"/>
<text x="399" y="140" class="tx">String</text>
<text x="399" y="172" class="mut">exclusif — personne d'autre ne regarde</text>
<!-- panel 3: rejected -->
<rect x="539" y="40" width="235" height="145" rx="8" class="panel"/>
<text x="656" y="62" class="ti">Les deux ensemble — rejeté</text>
<rect x="571" y="76" width="80" height="26" rx="4" class="boxbad"/>
<text x="611" y="94" class="tx">&amp;mut s</text>
<rect x="661" y="76" width="80" height="26" rx="4" class="boxbad"/>
<text x="701" y="94" class="tx">&amp;s</text>
<path d="M611,102 L611,112 L656,112" class="lnbad"/>
<path d="M701,102 L701,112 L656,112" class="lnbad"/>
<path d="M656,112 L656,120" class="lnbad" marker-end="url(#wr3b-arrowbad-fr)"/>
<rect x="586" y="120" width="140" height="30" rx="5" class="boxbad"/>
<text x="656" y="140" class="tx">String</text>
<text x="656" y="172" class="bad">le lecteur verrait une valeur incohérente</text>
<!-- footer -->
<text x="400" y="222" class="mut">Une seule règle couvre les quatre bugs ci-dessus : autant de lecteurs qu'on veut, ou un seul écrivain — jamais les deux</text>
</svg>
</div>

## Comparaison réelle

### La même Logique dans Différents Langages

**Version C (unsafe) :**
```c
char* process_data(char* input) {
    char* result = malloc(strlen(input) + 10);
    strcpy(result, input);
    strcat(result, " processed");
    return result;  // L'appelant doit se rappeler de free !
}

int main() {
    char* data = "hello";
    char* processed = process_data(data);
    printf("%s\n", processed);
    // Facile d'oublier: free(processed);
    return 0;
}
```

**Version Java (overhead GC) :**
```java
public String processData(String input) {
    return input + " processed";  // Crée des objets temporaires
}

public static void main(String[] args) {
    String data = "hello";
    String processed = processData(data);
    System.out.println(processed);
    // Le GC va finalement collecter les objets temporaires
}
```

**Version Rust (safe + fast) :**
```rust
fn process_data(input: &str) -> String {
    format!("{} processed", input)  // Mémoire gérée automatiquement
}

fn main() {
    let data = "hello";
    let processed = process_data(data);
    println!("{}", processed);
    // la variable processed est automatiquement supprimé à la fin du scope
}
```

## Caractéristiques performance

### Zero-Cost abstractions
Un code de haut niveau en apparence est traduit en code de bas niveau à la compilation.
```rust
// Code haut niveau...
let numbers: Vec<i32> = (0..1_000_000).collect();
let sum: i32 = numbers.iter().sum();

// ...compile vers le même code assembleur que:
let mut sum = 0;
for i in 0..1_000_000 {
    sum += i;
}
```

### Et il est même possible de contrôler l'emprunte mémoire
```rust
#[repr(C)]  // Même emprunte mémoire qu'un struct en C
struct Point {
    x: f32,
    y: f32,
    z: f32,
}

let points = vec![Point { x: 1.0, y: 2.0, z: 3.0 }; 1000];
// Emprunte mémoire contigu, pas d'overhead GC
```

## Sécurité niveau thread

### Prévention des Data Race (2 thread qui tentent d'accéder à la même ressource dont un en écriture et qui ne sont pas synchronisés)
```rust
use std::thread;

fn main() {
    let data = vec![1, 2, 3, 4, 5];
    
    thread::spawn(move || {
        println!("Data: {:?}", data);  // data moved vers le thread
    });
    
    // println!("{:?}", data);  // ❌ Erreur de compilation: data was moved
}
```

### Accès concurrent sécurisé
```rust
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}
```

**Pas de data races possibles** - vérifié au moment de la compilation.

## Comparaison des Features

| Feature | Rust | C | Java | Python |
|---------|------|---|------|--------|
| Free manuel | ❌ | ✅ | ❌ | ❌ |
| Thread GC | ❌ | ❌ | ✅ | ✅ |
| Memory safety compile-time | ✅ | ❌ | ❌ | ❌ |
| Garanties thread safety | ✅ | ❌ | ❌ | ❌ |
| Zero runtime overhead | ✅ | ✅ | ❌ | ❌ |
| Contrôle memory layout | ✅ | ✅ | ❌ | ❌ |
| Prévient use-after-free | ✅ | ❌ | ✅ | ✅ |
| Prévient double-free | ✅ | ❌ | ✅ | ✅ |
| Prévient memory leaks | ✅ | ❌ | ✅* | ✅* |

*\*Les langages GC peuvent avoir des memory leaks via les references*

## La garantie Rust

### Ce que Rust Élimine
**Memory leaks** - cleanup automatique  
**Use-after-free** - tracking d'ownership  
**Double-free** - ownership unique  
**Dangling pointers** - analyse des lifetimes  
**Buffer overflows** - bounds checking  
**Data races** - règles de borrowing  
**Iterator invalidation** - vérifications compile-time  

### Ce que tu obtiens
**Performance niveau C**  
**Memory safety**  
**Zero runtime overhead**  
🔒 **Thread safety**  
🔧 **Capacités systems programming**  

## Cas réels
### Dropbox Magic Pocket
- Ils ont remplacé Python par Rust pour le système de stockage
- **Performance :** 10x d'amélioration en efficacité CPU
- **Mémoire :** Usage prévisible, pas de pauses GC
- **Fiabilité :** Éliminé des classes entières de bugs

### Discord Chat Service
- Ils ont remplacé Go par Rust pour la gestion des messages  
- **Latence :** Temps de réponse constants sub-milliseconde
- **Mémoire :** Réduction de 40% de l'usage mémoire
- **Scaling :** Gère des millions de connexions concurrentes

### Mozilla Firefox
- Composants Rust dans le moteur de navigateur (Servo)
- **Sécurité :** Éliminé les vulnérabilités memory safety
- **Performance :** Rendu plus rapide, usage mémoire plus bas

## Le changement de paradigme
### Approche Traditionnelle
```
Code rapide → Gestion manuelle mémoire → Bugs
Code sûr → Garbage collection → Overhead performance
```

### Approche Rust
```
Compilateur intelligent → Système ownership → Code rapide + sûr
```

<div class="svg-container" style="margin:2rem 0;">
<svg class="rustevo-fig" viewBox="0 0 800 260" width="100%" style="height:auto;max-width:780px;display:block;margin:0 auto;" role="img" aria-label="L'évolution de C, rapide mais dangereux, vers les langages avec garbage collector, sûrs mais lents, vers Rust, à la fois rapide et sûr">
<style>
.rustevo-fig{--bg:#f8fafc;--box:#ffffff;--tx:#1e293b;--mut:#64748b;--ln:#cbd5e1;--ac:#FF6B00}
:root.dark .rustevo-fig,[data-theme="dark"] .rustevo-fig{--bg:#0f172a;--box:#1e293b;--tx:#f8fafc;--mut:#94a3b8;--ln:#475569}
.rustevo-fig text{font-family:ui-sans-serif,system-ui,sans-serif;fill:var(--tx)}
.rustevo-fig .title{font-size:15px;font-weight:700}
.rustevo-fig .body{font-size:12px;font-weight:600}
.rustevo-fig .cap{font-size:11px;fill:var(--mut)}
.rustevo-fig .box{fill:var(--box);stroke:var(--ln);stroke-width:1.5}
.rustevo-fig .acbox{fill:var(--ac);stroke:var(--ac)}
.rustevo-fig .ln{stroke:var(--ln);stroke-width:1.5;fill:none}
</style>
<!-- defs -->
<defs>
<marker id="rustevo-arrow-fr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" fill="var(--ln)"></path>
</marker>
</defs>
<!-- step 1: C -->
<rect class="box" x="20" y="80" width="210" height="110" rx="8"></rect>
<text x="125" y="108" text-anchor="middle" class="title">C</text>
<text x="125" y="130" text-anchor="middle" class="body">Rapide</text>
<text x="125" y="148" text-anchor="middle" class="cap">gestion mémoire manuelle</text>
<text x="125" y="163" text-anchor="middle" class="cap">unsafe — bugs au runtime</text>
<!-- step 2: GC languages -->
<rect class="box" x="295" y="80" width="210" height="110" rx="8"></rect>
<text x="400" y="108" text-anchor="middle" class="title">Java / Python / JS</text>
<text x="400" y="130" text-anchor="middle" class="body">Sûr</text>
<text x="400" y="148" text-anchor="middle" class="cap">garbage collector</text>
<text x="400" y="163" text-anchor="middle" class="cap">lent — overhead des pauses GC</text>
<!-- step 3: rust accent -->
<rect class="acbox" x="570" y="80" width="210" height="110" rx="8"></rect>
<text x="675" y="108" text-anchor="middle" class="title" fill="#ffffff">Rust</text>
<text x="675" y="130" text-anchor="middle" class="body" fill="#ffffff">Rapide ET Sûr</text>
<text x="675" y="148" text-anchor="middle" class="cap" fill="#ffffff">ownership, pas de GC</text>
<text x="675" y="163" text-anchor="middle" class="cap" fill="#ffffff">garanties compile-time</text>
<!-- arrows -->
<path class="ln" d="M230,135 L295,135" marker-end="url(#rustevo-arrow-fr)"></path>
<path class="ln" d="M505,135 L570,135" marker-end="url(#rustevo-arrow-fr)"></path>
<!-- caption -->
<text x="400" y="225" text-anchor="middle" class="cap">Rust n'est pas "C plus sûr" — c'est un contrat différent : pas besoin de runtime pour être sûr</text>
</svg>
</div>

## Ce que Rust apporte réellement
🦀 **Rust réunit le meilleur des deux mondes :**

**Performance prévisible** - pas de pauses GC, pas d'overhead runtime  
**Sécurité mémoire** - classes entières de bugs éliminées au moment de la compilation  
**Concurrence en mode zen** - data races préventées par le type system  
**Programmation systéme** - contrôle bas niveau quand nécessaire  
**Ergonomie moderne** - type system puissant, gestion de packages grâce à cargo  

---

## TL;DR

**L'Évolution :**
1. **C :** Rapide mais dangereux
2. **Java/Python/JS :** Sûr mais lent (overhead GC)
3. **Rust :** Rapide ET sûr (garanties compile-time)

**Rust n'est pas "C plus sûr".** C'est un contrat fondamentalement différent :

> "Tu n'as pas besoin d'un runtime pour être sûr — juste d'un compilateur intelligent."

**Le Résultat :** Sécurité màmoire et "[zero-cost abstraction](https://mayorana.ch/fr/blog/zero-cost-abstractions-rust)". Le saint graal de la programmation système.

---
