-
orestis.malaspin authoredorestis.malaspin authored
errors.md 4.83 KiB
title: Cours de programmation séquentielle
subtitle: Gestion d'erreurs
author: Orestis Malaspinas
sansfont: Sans Serif
Gestion d'erreurs
- Il est important de pouvoir gérer trois cas:
- La panique totale (erreur fatale du programme).
- L'erreur dont on peut se remettre.
- Un résultat qui peut contenir une valeur ou pas.
Panique!
panic!()
{.rust}
- Nous avons vu le macro
panic!("texte")
{.rust}. - Le programme s'arrête et affiche le
"texte"
{.rust}. - Utilisation:
-
Le programme ne doit pas continuer quoi qu'il arrive.
fn elem(v: &[i32], i: usize) -> i32 { if i >= v.len() { panic!("Erreur fatale!"); } // assert!(i < v.len(), "Erreur fatale!"); // ceci est équivalent v[i] } fn main() { let v = [1, 2, 3, 4]; elem(&v, 100); }
-
Avec l'appel
RUST_BACKTRACE=1
on peut remonter la pile d'appels (debugging).$ RUST_BACKTRACE=1 cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.01s Running `target/debug/ma_librairie` thread 'main' panicked at 'Erreur fatale!', src/main.rs:5:3 stack backtrace: 0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 1: std::sys_common::backtrace::print at libstd/sys_common/backtrace.rs:71 at libstd/sys_common/backtrace.rs:59 2: std::panicking::default_hook::{{closure}} at libstd/panicking.rs:211 3: std::panicking::default_hook at libstd/panicking.rs:227 4: std::panicking::rust_panic_with_hook at libstd/panicking.rs:477 5: std::panicking::begin_panic at /checkout/src/libstd/panicking.rs:411 6: ma_librairie::elem at src/main.rs:5 7: ma_librairie::main at src/main.rs:12 8: std::rt::lang_start::{{closure}} at /checkout/src/libstd/rt.rs:74 9: std::panicking::try::do_call at libstd/rt.rs:59 at libstd/panicking.rs:310 10: __rust_maybe_catch_panic at libpanic_unwind/lib.rs:102 11: std::rt::lang_start_internal at libstd/panicking.rs:289 at libstd/panic.rs:392 at libstd/rt.rs:58 12: std::rt::lang_start at /checkout/src/libstd/rt.rs:74 13: main 14: __libc_start_main 15: _start
-
Asserts
- On peut utiliser trois macros forts utiles.
:::::::::::::: {.columns} ::: {.column width="50%"}
-
assert!(cond, "Texte");
{.rust}
fn main() {
let num = 1;
let denum = 0;
assert!(denum != 0, "Le dénominateur doit être non nul.");
let _total = num / denum;
}
::: ::: {.column width="50%"}
-
assert_eq!(lhs, rhs, "Texte");
{.rust}
fn main() {
let a = 1;
let b = 0;
assert_eq!(a, b, "A et b devraient être égales.");
}
::: ::::::::::::::
-
assert_ne!(lhs, rhs, "Texte");
{.rust}
fn main() {
let a = 1;
let b = 0;
assert_ne!(a, b, "A et b devraient être différentes.");
}
Options
-
Un type énuméré particulièrement utile est le type
Option
{.rust}enum Option<T> { // <T> est une notation pour un type générique Some(T), None, }
-
Type utilisé lorsque une valeur peut être "quelque chose" ou "rien" (ex: recherche d'un élément dans un tableau).
-
Exmple: la division
fn main() { let num = 1; let denum = 4; let div = if denum == 0 { None } else { Some(num / denum) }; match div { Some(d) => println!("{} divisé par {} donne {}", num, denum, d), None => println!("Cette division n'existe pas."), } }
-
Il est commun que des fonction retournent des
Option
{.rust}.
Résultat
-
Pour un traitement plus fin des erreurs l'enum
enum Result<T, E> { Ok(T), Err(E), }
-
Contient le un élément de type
T
quand tout se passe bien etE
pour l'erreur.fn elem(v: &[i32], i: usize) -> Result<i32, &str> { if i >= v.len() { return Err("Erreur fatale!") } else { Ok(v[i]) } } fn main() { let v = [1, 2, 3, 4]; match elem(&v, 100) { Ok(i) => println!("L'élément est {}", i), Err(_) => println!("Mince ça a raté."), } }