ProgrammationDéveloppeur Backend

Comment fonctionne le mécanisme des slices dans Rust, quel types de slices existent, comment la sécurité est-elle garantie et que se passe-t-il si l'on essaie de dépasser les limites d'un slice ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Un slice dans Rust est une représentation dynamique d'une partie d'une collection dont les éléments sont stockés en mémoire de manière séquentielle. Un exemple typique de slice est &[T] ou &mut [T]. Les slices ne possèdent pas les données, mais font référence à un tampon externe. Tous les slices ont une longueur, qui est stockée avec la référence.

Types principaux :

  • &[T] — slice immuable
  • &mut [T] — slice mutable
  • Pour les chaînes : &str (en fait — un slice de bytes, toujours un UTF-8 valide)

La sécurité des slices est garantie au niveau du compilateur et de l'environnement d'exécution : toute tentative d'accéder à un élément en dehors des limites du slice provoquera une panique (panic) à l'exécution, aucune erreur irréconciliable en mémoire comme en C/C++ ne se produira.

Exemple :

let v = vec![1, 2, 3, 4, 5]; let s: &[i32] = &v[1..4]; // slice, référence aux éléments 2, 3, 4 println!("{:?}", s); // [2, 3, 4] // s[3]; // panic! (débordement)

Question piège

Peut-il y avoir des slices vides ? Quelle est la différence entre un slice vide et None ?

Réponse : Oui, les slices peuvent être vides (&[]), cela signifie une référence à une partie de données avec une longueur nulle, mais ce n'est pas l'équivalent de None. Un slice vide est sûr à utiliser, tandis que Option<&[T]> sert à distinguer "y a-t-il un slice du tout".

Exemple :

let s: &[i32] = &[]; assert!(s.is_empty()); // Option<&[i32]> est utilisé si le slice peut ne pas exister du tout.

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans un grand service de journalisation, un programmeur a utilisé un slice basé sur une plage calculée dynamiquement à partir des données utilisateur. Lors du calcul incorrect de la slice (par exemple, si start > end ou si end > len), le code fonctionnait lors des tests, mais en production a provoqué une "panic" et a arrêté le processus sous forte charge.


Histoire

Dans une bibliothèque interne d'hachage concurremt, &mut [T] était utilisé et plusieurs threads prenaient simultanément différents slices d'un même tableau. Un thread modifiait le slice, tandis qu'un autre prenait un autre slice de la même mémoire. Le programme s'est compilé, mais en raison d'un mauvais partitionnement, des UB pouvaient se produire via du code non sûr (utilisation de unsafe), si les slices se chevauchaient.


Histoire

Dans un parseur système de paquets réseau, un slice était créé de manière non sécurisée (pointeur brut et from_raw_parts). Le développeur avait oublié de vérifier la validité de la longueur du paquet d'entrée. En conséquence, une tentative de lecture en dehors des limites a entraîné un plantage de l'application et une vulnérabilité (accès OOB potentiel), qui aurait pu être évitée par une bonne utilisation des slices sûrs.