-
Notifications
You must be signed in to change notification settings - Fork 50
Raw pointer #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Raw pointer #51
Changes from 3 commits
8c2a693
fa895f2
ddf9ac4
3529cab
b5c8d80
ba1bc8a
4716c7f
3d4ca30
4fcfeb4
ab8a1b7
2d9b485
97781d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -223,3 +223,74 @@ d'autres raisons. | |
| <mark>TODO</mark> : complexité cyclomatique du code macro-expansé, limites de | ||
| récursion, ... | ||
| --> | ||
|
|
||
| ## Déplacement de valeurs | ||
|
|
||
| Rust propose trois différents modes de déplacement de valeur: | ||
|
|
||
| - Soit par *déplacement*, qui est le comportement par défaut. | ||
| - Ou par *déplacement* plus un *drop* de la valeur si le type implément le trait `Drop`. | ||
|
ricked-twice marked this conversation as resolved.
Outdated
|
||
| - Ou par *copie*, si son type implémente le trait `Copy` | ||
|
|
||
| Cependant, des problèmes peuvent être constater lors de l'utilisation de la fonction `std::ptr::read`. | ||
|
ricked-twice marked this conversation as resolved.
Outdated
|
||
| Selon la [documentation](https://doc.rust-lang.org/std/ptr/fn.read.html), cette fonction: | ||
| > Lis la valeur pointée par src sans la déplacer. Ce qui laisse la mémoire pointée intact. | ||
|
|
||
| Cette fonction est donc responsable d'effectuer une copie de la valeur pointée, indépemment du mode de déplacement du type en question. | ||
| Ce comportement peut être dangeureux car il peut mener à des *double-free* et/ou des *double-drop*. | ||
|
|
||
| Pour illustrer ce comportement, considérons le code suivant : | ||
|
|
||
| ```rust | ||
| # use std::ops::Drop; | ||
| # | ||
| #[derive(Debug)] | ||
| struct MyStruct(u8); | ||
|
|
||
| impl Drop for MyStruct { | ||
| fn drop(&mut self) { | ||
| # println!("---Dropping an object---\nBefore zeroing: {} @ {:p}", self.0, &self.0 as *const u8); | ||
| self.0 = 0; | ||
| # println!("After zeroing: {} @ {:p}", self.0, &self.0 as *const u8); | ||
| } | ||
| } | ||
|
ricked-twice marked this conversation as resolved.
Outdated
|
||
|
|
||
| fn main(){ | ||
| let obj: MyStruct = MyStruct(100); | ||
| let ptr: *const MyStruct = &test as *const MyStruct; | ||
| println!("{:?} @ {:p}", unsafe { std::ptr::read(ptr) }, ptr); | ||
| } | ||
|
Comment on lines
+256
to
+260
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Donner le résultat obtenu après exécution du programme |
||
| ``` | ||
|
|
||
| On peut observer qu'un deuxième objet a implicitement été créé lors de l'appel à `std::ptr::read`, i.e. une copie d'un objet *non copiable* est effectuée. | ||
| Ici, le problème n'est pas réellement dangeureux, sauf si du nettoyage de mémoire en dehors de l'implémentation de `drop` est réalisée (tel que recommandé): des données sensibles peuvent donc persister en mémoire. | ||
|
|
||
| Mais ce comportement peut causer des problèmes de résilience lors de l'utilisation de cette fonction avec un *raw pointer* pointant vers des données allouées sur le tas avec un mode de déplacement par déplacement, tel qu'illustré ici : | ||
|
|
||
| ```rust | ||
| # use std::boxed::Box; | ||
| # use std::ops::Drop; | ||
| # | ||
| #[derive(Debug)] | ||
| struct MyStructBoxed(Box<u8>); | ||
|
|
||
| impl Drop for MyStructBoxed { | ||
| fn drop(&mut self) { | ||
| # println!("---Dropping an object---\nBefore zeroing: {} @ {:p}", self.0, self.0); | ||
| let value: &mut u8 = self.0.as_mut(); | ||
| *value = 0; | ||
| # println!("After zeroing: {} @ {:p}", self.0, self.0); | ||
| } | ||
| } | ||
|
|
||
| fn main(){ | ||
| let test: MyStructBoxed = MyStructBoxed(Box::new(100)); | ||
| let ptr: *const MyStructBoxed = &test as *const MyStructBoxed; | ||
| println!("{:?} @ {:p}", unsafe { std::ptr::read(ptr) }, unsafe { &*ptr }.0 ); | ||
| } | ||
| ``` | ||
|
Comment on lines
+227
to
+311
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je pense que cette partie n'est pas nécessaire à la justification de la règle. En effet, un pointeur raw n'est, dans la pratique, pas utilisable sans unsafe. |
||
|
|
||
| > ### Règle {{#check LANG-RAW-PTR | Éviter d'utiliser `std::ptr::read`}} | ||
| > | ||
| > `std::ptr::read` peut avoir des effets de bords indésirables en fonction du mode déplacement du type pointé par le *raw pointer* source. | ||
| > Il est donc préférable d'utiliser l'opération de référencement/déréférencement (`&*`) pour les éviter. | ||
Uh oh!
There was an error while loading. Please reload this page.