---
title: "Comment l'ownership prévient-il les memory leaks et data races ?"
description: "Comment les règles d'ownership ferment la porte aux fuites mémoire et aux data races avant même l'exécution — et où elles s'arrêtent."
url: "https://mayorana.ch/fr/blog/ownership-safety-rust-fr"
language: "fr"
date: "2025-11-26"
author: "Mohamed Bennekrouf"
tags:
  - "rust"
  - "memory"
  - "ownership"
  - "borrowing"
  - "data-races"
en_version: "https://mayorana.ch/en/blog/ownership-safety-rust.md"
---

# Comment l'ownership prévient-il les memory leaks et data races ?

L'ownership est le système central de gestion mémoire de Rust, appliquant des règles strictes au moment de la compilation pour assurer la sécurité sans [garbage collector](https://mayorana.ch/fr/blog/why-garbage-collector-fr). Il prévient les memory leaks et data races à travers une combinaison de règles d'ownership, move semantics, et borrowing.

<div class="svg-container" style="margin:2rem 0;">
<svg class="mm4-fig" viewBox="0 0 800 240" width="100%" style="height:auto;max-width:780px;display:block;margin:0 auto;" role="img" aria-label="Déplacer un String de s1 vers s2 transfère l'ownership des données heap et invalide s1">
<style>
.mm4-fig{--bg:#f8fafc;--box:#ffffff;--tx:#1e293b;--mut:#64748b;--ln:#cbd5e1;--ac:#FF6B00}
:root.dark .mm4-fig,[data-theme="dark"] .mm4-fig{--bg:#0f172a;--box:#1e293b;--tx:#f8fafc;--mut:#94a3b8;--ln:#475569}
.mm4-fig .box{fill:var(--box);stroke:var(--ln);stroke-width:1.5}
.mm4-fig .acbox{fill:var(--box);stroke:var(--ac);stroke-width:2}
.mm4-fig .deadbox{fill:none;stroke:var(--mut);stroke-width:1.5;stroke-dasharray:4 3}
.mm4-fig .title{font:700 14px ui-sans-serif,system-ui,sans-serif;fill:var(--tx)}
.mm4-fig .body{font:600 12px ui-sans-serif,system-ui,sans-serif;fill:var(--tx)}
.mm4-fig .cap{font:11px ui-sans-serif,system-ui,sans-serif;fill:var(--mut)}
.mm4-fig .ac{fill:var(--ac)}
.mm4-fig .mut{fill:var(--mut)}
.mm4-fig path{stroke:var(--ln);stroke-width:1.5;fill:none}
</style>
<defs>
<marker id="mm4-arrow-fr" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" style="fill:var(--ac)"/></marker>
</defs>
<!-- s1 box, now invalid -->
<rect x="40" y="40" width="200" height="70" rx="8" class="deadbox"/>
<text x="140" y="66" text-anchor="middle" class="body mut">s1 (moved)</text>
<text x="140" y="84" text-anchor="middle" class="cap">invalide : use after move</text>
<!-- s2 box, valid owner -->
<rect x="330" y="40" width="200" height="70" rx="8" class="acbox"/>
<text x="430" y="66" text-anchor="middle" class="title ac">s2</text>
<text x="430" y="84" text-anchor="middle" class="cap">nouveau propriétaire du String</text>
<!-- heap box -->
<rect x="590" y="40" width="180" height="70" rx="8" class="box"/>
<text x="680" y="66" text-anchor="middle" class="body">"hello"</text>
<text x="680" y="84" text-anchor="middle" class="cap">buffer heap (inchangé)</text>
<!-- arrows -->
<path d="M240,75 L330,75" marker-end="url(#mm4-arrow-fr)"/>
<text x="285" y="65" text-anchor="middle" class="cap">move</text>
<path d="M530,75 L590,75" style="stroke:var(--ac)" marker-end="url(#mm4-arrow-fr)"/>
<!-- scope note -->
<rect x="40" y="150" width="730" height="60" rx="8" class="box"/>
<text x="405" y="175" text-anchor="middle" class="body">take_ownership(s)  →  s droppé en fin de scope de la fonction</text>
<text x="405" y="193" text-anchor="middle" class="cap">un seul propriétaire à la fois : pas de double free, pas de fuite</text>
</svg>
</div>

## Ownership en Rust

- Chaque valeur a un **propriétaire unique** (variable).
- Quand le propriétaire sort du scope, la valeur est **droppée** (trait `Drop` appelé).
- L'ownership peut être **transféré** (moved), rendant la variable originale invalide.

## Règles clés

### Move Semantics

Assigner une valeur heap-allocated (ex : `String`) à une autre variable transfère l'ownership, invalidant l'originale.

**Exemple** :
```rust
let s1 = String::from("hello");
let s2 = s1; // Ownership moved vers s2
// println!("{}", s1); // Erreur de compilation: value borrowed after move
```

### Copy vs. Move

- Les types avec **taille connue** (`i32`, `bool`) implémentent `Copy` et sont clonés automatiquement.
- Les types heap-allocated (`String`, `Vec`) n'implémentent pas `Copy` et sont moved.

### Appels de Function

Passer une valeur à une fonction la move ou la copie, suivant les mêmes règles.

**Exemple** :
```rust
fn take_ownership(s: String) { /* ... */ }

let s = String::from("hello");
take_ownership(s); // Ownership moved dans la fonction
// println!("{}", s); // Erreur: s est invalide
```

## Comment l'Ownership prévient les Memory Leaks

- **Cleanup Automatique** : Quand le propriétaire sort du scope, Rust appelle `drop` pour libérer la mémoire (pas de `free()` manuel nécessaire).
- **Pas de Double Frees** : Puisque seul un propriétaire existe, la valeur est droppée exactement une fois.

## Comment l'Ownership prévient les Data Races

- **Règles de Borrowing** :
  - **Emprunts immutables** (`&T`) : Plusieurs autorisés, mais aucun emprunt mutable ne peut coexister.
  - **Emprunts mutables** (`&mut T`) : Un seul autorisé, et aucun autre emprunt ne peut exister.
- **Application au Compile-Time** : Le compilateur rejette le code qui pourrait mener à des data races.

**Exemple : Prévention de Data Race** :
```rust
let mut data = vec![1, 2, 3];
let r1 = &data; // Borrowing immutable OK
let r2 = &data; // Autre borrow immutable OK
// let r3 = &mut data; // ERREUR: Cannot borrow as mutable while immutable borrows exist
println!("{:?}, {:?}", r1, r2);
```

<div class="svg-container" style="margin:2rem 0;">
<svg class="mm4-fig2" viewBox="0 0 800 320" width="100%" style="height:auto;max-width:780px;display:block;margin:0 auto;" role="img" aria-label="Matrice des emprunts autorisés selon les emprunts déjà vivants, mettant en évidence le refus d'un emprunt mutable tant que des emprunts partagés existent">
<style>
.mm4-fig2{--bg:#f8fafc;--box:#ffffff;--tx:#1e293b;--mut:#64748b;--ln:#cbd5e1;--ac:#FF6B00}
:root.dark .mm4-fig2,[data-theme="dark"] .mm4-fig2{--bg:#0f172a;--box:#1e293b;--tx:#f8fafc;--mut:#94a3b8;--ln:#475569}
.mm4-fig2 .box{fill:var(--box);stroke:var(--ln);stroke-width:1.5}
.mm4-fig2 .acbox{fill:var(--box);stroke:var(--ac);stroke-width:2}
.mm4-fig2 .title{font:700 14px ui-sans-serif,system-ui,sans-serif;fill:var(--tx)}
.mm4-fig2 .head{font:700 13px ui-sans-serif,system-ui,sans-serif;fill:var(--mut)}
.mm4-fig2 .body{font:600 12px ui-sans-serif,system-ui,sans-serif;fill:var(--tx)}
.mm4-fig2 .cap{font:11px ui-sans-serif,system-ui,sans-serif;fill:var(--mut)}
.mm4-fig2 .ac{fill:var(--ac)}
.mm4-fig2 path{stroke:var(--ln);stroke-width:1.5;fill:none}
</style>
<defs>
<marker id="mm4b-arrow" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" style="fill:var(--ln);stroke:none"/></marker>
<marker id="mm4b-arrow-ac" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" style="fill:var(--ac);stroke:none"/></marker>
</defs>
<!-- title -->
<text x="400" y="24" text-anchor="middle" class="title">Ce que le borrow checker autorise ensuite</text>
<!-- column headers -->
<text x="50" y="80" class="head">Emprunts déjà vivants</text>
<text x="425" y="80" text-anchor="middle" class="head">tu demandes &amp;data</text>
<text x="625" y="80" text-anchor="middle" class="head">tu demandes &amp;mut data</text>
<!-- row 1 -->
<text x="50" y="130" class="body">aucun</text>
<rect x="330" y="96" width="190" height="58" rx="8" class="box"/>
<text x="425" y="122" text-anchor="middle" class="body">autorisé</text>
<text x="425" y="140" text-anchor="middle" class="cap">premier emprunt partagé</text>
<rect x="530" y="96" width="190" height="58" rx="8" class="box"/>
<text x="625" y="122" text-anchor="middle" class="body">autorisé</text>
<text x="625" y="140" text-anchor="middle" class="cap">accès exclusif</text>
<!-- row 2 -->
<text x="50" y="190" class="body">r1 = &amp;data, r2 = &amp;data</text>
<text x="50" y="208" class="cap">autant de partagés que voulu</text>
<rect x="330" y="162" width="190" height="58" rx="8" class="box"/>
<text x="425" y="188" text-anchor="middle" class="body">autorisé</text>
<text x="425" y="206" text-anchor="middle" class="cap">les partagés s'accumulent</text>
<rect x="530" y="162" width="190" height="58" rx="8" class="acbox"/>
<text x="625" y="188" text-anchor="middle" class="body ac">refusé</text>
<text x="625" y="206" text-anchor="middle" class="cap">cannot borrow as mutable</text>
<!-- row 3 -->
<text x="50" y="256" class="body">m = &amp;mut data</text>
<text x="50" y="274" class="cap">exactement un</text>
<rect x="330" y="228" width="190" height="58" rx="8" class="box"/>
<text x="425" y="254" text-anchor="middle" class="body">refusé</text>
<text x="425" y="272" text-anchor="middle" class="cap">déjà emprunté mutablement</text>
<rect x="530" y="228" width="190" height="58" rx="8" class="box"/>
<text x="625" y="254" text-anchor="middle" class="body">refusé</text>
<text x="625" y="272" text-anchor="middle" class="cap">un seul &amp;mut à la fois</text>
<!-- pointer to the highlighted cell -->
<path d="M760,191 L720,191" style="stroke:var(--ac)" marker-end="url(#mm4b-arrow-ac)"/>
<!-- caption -->
<text x="400" y="308" text-anchor="middle" class="cap">Dans l'exemple r1 et r2 sont encore vivants, donc `let r3 = &amp;mut data;` tombe dans la case surlignée.</text>
</svg>
</div>

## Points clés
**L'ownership assure** :
- Pas de [dangling pointers](https://mayorana.ch/fr/blog/dangling-pointer-rust-fr) (via lifetimes).
- Pas de memory leaks (via `Drop`).
- Pas de data races (via règles de borrowing).

Le modèle d'ownership de Rust garantit la memory safety et concurrency safety au moment de la compilation, délivrant performance et fiabilité.
