<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>~rom1v/blog</title>
 <link href="https://blog.rom1v.com/category/planet-libre/feed/" rel="self"/>
 <link href="https://blog.rom1v.com/"/>
 <updated>2026-04-30T12:26:04+02:00</updated>
 <id>https://blog.rom1v.com/</id>
 <author>
   <name>Romain Vimont</name>
   <email>rom@rom1v.com</email>
 </author>

 
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
   
 <entry>
   <title>Gnirehtet réécrit en Rust</title>
   <link href="https://blog.rom1v.com/2017/09/gnirehtet-reecrit-en-rust/"/>
   <updated>2017-09-21T17:00:00+02:00</updated>
   <id>https://blog.rom1v.com/2017/09/gnirehtet-reecrit-en-rust</id>
   <content type="html">&lt;p&gt;Il y a quelques mois, j’ai présenté &lt;a href=&quot;/2017/03/gnirehtet/&quot;&gt;Gnirehtet&lt;/a&gt;, un outil de
&lt;em&gt;reverse tethering&lt;/em&gt; pour Android que j’ai écrit en Java.&lt;/p&gt;

&lt;p&gt;Depuis, &lt;strong&gt;je l’ai réécrit en &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Et il est également open source ! &lt;a href=&quot;https://github.com/Genymobile/gnirehtet&quot;&gt;Téléchargez-le&lt;/a&gt;, branchez un
téléphone ou une tablette Android, et exécutez :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./gnirehtet run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(adb doit être installé)&lt;/em&gt;&lt;/p&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#pourquoi-rust&quot; id=&quot;markdown-toc-pourquoi-rust&quot;&gt;Pourquoi Rust?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#apprendre-rust&quot; id=&quot;markdown-toc-apprendre-rust&quot;&gt;Apprendre Rust&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#difficultés&quot; id=&quot;markdown-toc-difficultés&quot;&gt;Difficultés&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#encapsulation&quot; id=&quot;markdown-toc-encapsulation&quot;&gt;Encapsulation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#observateur&quot; id=&quot;markdown-toc-observateur&quot;&gt;Observateur&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#partage-de-données-mutables&quot; id=&quot;markdown-toc-partage-de-données-mutables&quot;&gt;Partage de données mutables&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#limitations-du-compilateur&quot; id=&quot;markdown-toc-limitations-du-compilateur&quot;&gt;Limitations du compilateur&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sûreté-et-pièges&quot; id=&quot;markdown-toc-sûreté-et-pièges&quot;&gt;Sûreté et pièges&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#leakpocalypse&quot; id=&quot;markdown-toc-leakpocalypse&quot;&gt;Leakpocalypse&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#infinité-indéfinie&quot; id=&quot;markdown-toc-infinité-indéfinie&quot;&gt;Infinité indéfinie&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#erreur-de-segmentation&quot; id=&quot;markdown-toc-erreur-de-segmentation&quot;&gt;Erreur de segmentation&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#stats&quot; id=&quot;markdown-toc-stats&quot;&gt;Stats&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#nombre-de-lignes&quot; id=&quot;markdown-toc-nombre-de-lignes&quot;&gt;Nombre de lignes&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#taille-des-binaires&quot; id=&quot;markdown-toc-taille-des-binaires&quot;&gt;Taille des binaires&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#utilisation-mémoire&quot; id=&quot;markdown-toc-utilisation-mémoire&quot;&gt;Utilisation mémoire&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#utilisation-cpu&quot; id=&quot;markdown-toc-utilisation-cpu&quot;&gt;Utilisation CPU&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;pourquoi-rust&quot;&gt;Pourquoi Rust?&lt;/h2&gt;

&lt;p&gt;À Genymobile, nous voulions que &lt;em&gt;Gnirehtet&lt;/em&gt; ne nécessite pas d’environnement
d’exécution Java (JRE), donc le besoin principal était de compiler l’application
vers un binaire exécutable &lt;em&gt;natif&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Par conséquent, j’ai d’abord pensé la réécrire en C ou C++. Mais à ce moment-là
(début mai), apprendre Rust m’intéressait, après avoir vaguement entendu parler
de ses fonctionnalités:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html&quot;&gt;sûreté mémoire sans &lt;em&gt;garbage collection&lt;/em&gt;&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html&quot;&gt;concurrence sans &lt;em&gt;data races&lt;/em&gt;&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.rust-lang.org/2015/05/11/traits.html&quot;&gt;abstraction sans coût&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cependant, je n’avais jamais écrit une ligne de Rust ni entendu parler de son
système de &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/ownership.html&quot;&gt;possession&lt;/a&gt;, d’&lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html&quot;&gt;emprunt&lt;/a&gt; ou de &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/lifetimes.html&quot;&gt;durées de
vie&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mais je suis convaincu que le meilleur moyen d’apprendre un langage de
programmation est de travailler à plein temps sur un projet dans ce langage.&lt;/p&gt;

&lt;p&gt;J’étais motivé, donc après avoir vérifié que ça pouvait convenir (en gros, j’ai
écrit un exemple utilisant la bibliothèque d’&lt;a href=&quot;https://en.wikipedia.org/wiki/Asynchronous_I/O&quot;&gt;I/O asynchrone&lt;/a&gt; &lt;a href=&quot;https://crates.io/crates/mio&quot;&gt;mio&lt;/a&gt;,
et je l’ai exécuté à la fois sur Linux et Windows), j’ai décidé de réécrire
&lt;em&gt;Gnirehtet&lt;/em&gt; en Rust.&lt;/p&gt;

&lt;h2 id=&quot;apprendre-rust&quot;&gt;Apprendre Rust&lt;/h2&gt;

&lt;p&gt;Pendant la réécriture, j’ai &lt;em&gt;dévoré&lt;/em&gt; successivement le &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/&quot;&gt;Rust book&lt;/a&gt;, &lt;a href=&quot;https://rustbyexample.com/&quot;&gt;Rust by
example&lt;/a&gt; et le &lt;a href=&quot;https://doc.rust-lang.org/nomicon/&quot;&gt;Rustonomicon&lt;/a&gt;. J’ai beaucoup appris, et j’aime énormément ce
langage. Beaucoup de ses fonctionnalités me manquent maintenant quand je
travaille sur un projet C++ :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://rustbyexample.com/cast/inference.html&quot;&gt;inférence de type avancée&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/enums.html&quot;&gt;enums&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/patterns.html&quot;&gt;patterns&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/traits.html&quot;&gt;trait bounds&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/std/option/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; (comme &lt;a href=&quot;https://github.com/tvaneerd/cpp17_in_TTs/blob/master/ALL_IN_ONE.md#stdoptionalt&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::optional&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; en C++17, mais tirant bénéfice des
enums et des patterns),&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/macros.html&quot;&gt;macros hygiéniques&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;l’absence de fichiers d’en-têtes,&lt;/li&gt;
  &lt;li&gt;le (si simple) système de &lt;em&gt;build&lt;/em&gt;, &lt;em&gt;et bien sûr&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;la garantie de sûreté mémoire.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;À propos de l’apprentissage, Paul Graham &lt;a href=&quot;http://paulgraham.com/know.html&quot;&gt;a écrit&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Reading and experience train your model of the world.&lt;/strong&gt; And even if you
forget the experience or what you read, its effect on your model of the world
persists. Your mind is like a compiled program you’ve lost the source of. It
works, but you don’t know why.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pour les non-anglophones, ma propre traduction :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;La lecture et l’expérience entraînent votre modèle du monde.&lt;/strong&gt; Et même si
vous oubliez l’expérience ou ce que vous avez lu, son effet sur votre modèle
du monde persiste. Votre esprit est comme un programme compilé dont vous
auriez perdu le code source. Ça fonctionne, mais vous ne savez pas pourquoi.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Certains des concepts de Rust (comme les &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/lifetimes.html&quot;&gt;durées de vie&lt;/a&gt; ou la
&lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/ownership.html#move-semantics&quot;&gt;sémantique de mouvement&lt;/a&gt; par défaut) m’ont fourni un &lt;em&gt;jeu de
données&lt;/em&gt; significativement différent, qui a sans aucun doute affecté mon modèle
du monde (de la programmation).&lt;/p&gt;

&lt;p&gt;Je ne vais pas présenter toutes ces fonctionnaliés (cliquez sur les liens de la
documentation si ça vous intéresse). À la place, je vais essayer d’expliquer où
et pourquoi Rust a resisté au &lt;em&gt;design&lt;/em&gt; que je voulais implémenter, et comment
repenser les problèmes dans le périmètre des contraintes de Rust.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;La partie suivant nécessite une certaine connaissance de Rust. Vous pourriez
vouloir la passer pour aller directement aux &lt;a href=&quot;#stats&quot;&gt;stats&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;difficultés&quot;&gt;Difficultés&lt;/h2&gt;

&lt;p&gt;Je trouvais la conception de l’application Java plutôt réussie, donc je voulais
reproduire l’architecture globale dans la version Rust (avec d’éventuelles
adaptations pour la &lt;em&gt;rustifier&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Mais j’ai lutté sur les détails, en particulier pour satisfaire le &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html&quot;&gt;&lt;em&gt;borrow
checker&lt;/em&gt;&lt;/a&gt;. Les &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html#the-rules&quot;&gt;règles&lt;/a&gt; sont simples:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;First, any borrow must last for a scope no greater than that of the owner.
Second, you may have one or the other of these two kinds of borrows, but not
both at the same time:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;one or more references (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;T&lt;/code&gt;) to a resource,&lt;/li&gt;
    &lt;li&gt;exactly one mutable reference (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut T&lt;/code&gt;).&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;En français :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Premièrement, aucun emprunt ne doit avoir une portée plus grande que celle de
son propriétaire.
Deuxièmement, vous pouvez avoir l’un ou l’autre de ces types d’emprunts, mais
pas les deux à la fois:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;une ou plusieurs références (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;T&lt;/code&gt;) vers une ressource,&lt;/li&gt;
    &lt;li&gt;exactement une référence mutable (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut T&lt;/code&gt;).&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cependant, il m’a fallu un peu de temps pour réaliser comment elles entrent en
conflit avec certains principes ou modèles de conception.&lt;/p&gt;

&lt;p&gt;Voici donc mes retours. J’ai sélectionné 4 sujets qui sont suffisamment généraux
pour être indépendants de ce projet particulier :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;les conflits avec l’&lt;a href=&quot;#encapsulation&quot;&gt;encapsulation&lt;/a&gt; ;&lt;/li&gt;
  &lt;li&gt;le &lt;em&gt;design pattern&lt;/em&gt; &lt;a href=&quot;#observateur&quot;&gt;observateur&lt;/a&gt; ;&lt;/li&gt;
  &lt;li&gt;comment &lt;a href=&quot;#partage-de-donnes-mutables&quot;&gt;partager des données mutables&lt;/a&gt; ;&lt;/li&gt;
  &lt;li&gt;un retour rapide sur les &lt;a href=&quot;#limitations-du-compilateur&quot;&gt;limitations ennuyeuses du
compilateur&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;encapsulation&quot;&gt;Encapsulation&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Les règles d’emprunt contraignent l’encapsulation.&lt;/strong&gt; C’est la première
conséquence que j’ai réalisée.&lt;/p&gt;

&lt;p&gt;Voici un exemple canonique :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.header&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.payload&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nous créons juste une nouvelle instance de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data&lt;/code&gt;, puis associons à des
variables locales des références mutables vers les tableaux &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;header&lt;/code&gt; et
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt;, en passant par des accesseurs.&lt;/p&gt;

&lt;p&gt;Cependant, cela ne compile pas :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rustc sample.rs
error[E0499]: cannot borrow `data` as mutable more than once at a time
  --&amp;gt; sample.rs:21:19
   |
25 |     let header = data.header();
   |                  ---- first mutable borrow occurs here
26 |     let payload = data.payload();
   |                   ^^^^ second mutable borrow occurs here
27 | }
   | - first borrow ends here
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Le compilateur ne peut pas faire l’hypothèse que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;header()&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload()&lt;/code&gt;
retournent des références vers des données disjointes dans la structure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data&lt;/code&gt;.
Par conséquent, chacun &lt;em&gt;emprunte&lt;/em&gt; la structure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; entièrement. Vu que les
règles d’emprunt interdisent d’obtenir deux références mutables vers la même
ressource, il rejette le second appel.&lt;/p&gt;

&lt;p&gt;Parfois, nous faisons face à des limitations temporaires parce que le
compilateur n’est pas (encore) assez malin. Ce n’est pas le cas ici :
l’implémentation de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;header()&lt;/code&gt; pourrait très bien retourner une référence vers
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt;, ou écrire dans le tableau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt;, enfreignant ainsi les règles
d’emprunt. Et la validité d’un appel d’une méthode ne peut pas dépendre de
l’implementation de la méthode.&lt;/p&gt;

&lt;p&gt;Pour corriger le problème, le compilateur doit être capable de savoir que les
variables locales &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;header&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt; référencent des &lt;strong&gt;données disjointes&lt;/strong&gt;,
par exemple en accédant aux champs directement :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;ou en exposant une méthode fournissant les deux références simultanément :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;header_and_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.header_and_payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;De même, dans l’implémentation d’une structure, les règles d’emprunt empêchent
de factoriser du code dans une méthode privée facilement. Prenons cet exemple
(artificiel) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;prefix_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.prefix_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.cloned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.prefix_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ici, le champ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buf&lt;/code&gt; est un tableau stockant un préfixe et un contenu de manière
contiguë.&lt;/p&gt;

&lt;p&gt;Nous voulons factoriser la manière dont nous récupérons la &lt;em&gt;slice&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;content&lt;/code&gt;,
pour que les méthodes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update_*()&lt;/code&gt; n’aient pas à se préoccuper des détails.
Essayons :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt; impl Data {
     pub fn update_sum(&amp;amp;mut self) {
&lt;span class=&quot;gd&quot;&gt;-        let content = &amp;amp;self.buf[self.prefix_length..];
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+        let content = self.content();
&lt;/span&gt;         self.sum = content.iter().cloned().map(u32::from).sum();
     }

     pub fn update_port(&amp;amp;mut self) {
&lt;span class=&quot;gd&quot;&gt;-        let content = &amp;amp;self.buf[self.prefix_length..];
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+        let content = self.content();
&lt;/span&gt;         self.port = (content[2] as u16) &amp;lt;&amp;lt; 8 | content[3] as u16;
     }
&lt;span class=&quot;gi&quot;&gt;+
+    fn content(&amp;amp;mut self) -&amp;gt; &amp;amp;[u8] {
+        &amp;amp;self.buf[self.prefix_length..]
+    }
&lt;/span&gt; }&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Malheureusement, cela ne compile pas :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error[E0506]: cannot assign to `self.sum` because it is borrowed
  --&amp;gt; facto2.rs:11:9
   |
10 |         let content = self.content();
   |                       ---- borrow of `self.sum` occurs here
11 |         self.sum = content.iter().cloned().map(u32::from).sum();
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.sum` occurs here

error[E0506]: cannot assign to `self.port` because it is borrowed
  --&amp;gt; facto2.rs:16:9
   |
15 |         let content = self.content();
   |                       ---- borrow of `self.port` occurs here
16 |         self.port = (content[2] as u16) &amp;lt;&amp;lt; 8 &amp;amp; content[3] as u16;
   |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Comme dans l’exemple précédent, récupérer une référence à travers une méthode
&lt;em&gt;emprunte&lt;/em&gt; la structure complète (ici, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Pour contourner le problème, nous pouvons expliquer au compilateur que les
champs sont disjoints :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.prefix_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.cloned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.prefix_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ça compile, mais cela va totalement à l’encontre de la factorisation :
l’appelant doit fournir les champs nécessaires.&lt;/p&gt;

&lt;p&gt;Comme alternative, nous pouvons utiliser une &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/macros.html&quot;&gt;macro&lt;/a&gt; pour &lt;em&gt;inliner&lt;/em&gt; le
code :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;nd&quot;&gt;macro_rules!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$self:ident&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.prefix_length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;content!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.cloned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;content!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais c’est loin d’être idéal.&lt;/p&gt;

&lt;p&gt;Je pense que nous devons juste l’accepter : l’encapsulation entre parfois en
conflit avec les règles d’emprunt. Après tout, ce n’est pas si surprenant :
imposer les règles d’emprunt nécessite de suivre chaque accès concret aux
ressources, alors que l’encapsulation vise à les abstraire.&lt;/p&gt;

&lt;h3 id=&quot;observateur&quot;&gt;Observateur&lt;/h3&gt;

&lt;p&gt;Le &lt;em&gt;design pattern&lt;/em&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;observateur&lt;/a&gt; est utile pour enregistrer des
événements sur un objet.&lt;/p&gt;

&lt;p&gt;Dans certains cas, &lt;strong&gt;ce pattern pose des difficultés d’implémentation en Rust&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pour faire simple, considérons que les événements sont des valeurs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u32&lt;/code&gt;. Voici
une implémentation possible :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventListener&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Notifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EventListener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Notifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventListener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.listeners&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.listeners&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;listener&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.on_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Par commodité, implémentons notre trait &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventListener&lt;/code&gt; pour les closures :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventListener&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ainsi, son utilisation est simple :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;received [{}]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;notifying...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Cela affiche :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;notifying...
received [42]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Jusqu’ici, tout va bien.&lt;/p&gt;

&lt;p&gt;Cependant, les choses se compliquent si nous voulons modifier un état sur la
réception d’un événement. Par exemple, implémentons une structure pour stocker
tous les événements reçus :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.events&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.events&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour pouvoir remplir ce &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt; sur chaque événement reçu, nous devons d’une
manière ou d’une autre le passer avec l’&lt;em&gt;event listener&lt;/em&gt;, qui sera stocké dans
le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Notifier&lt;/code&gt;. Par conséquent, nous avons besoin qu’une instance de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt;
soit &lt;strong&gt;partagée&lt;/strong&gt; entre le code appelant et le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Notifier&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Avoir deux références mutables vers le même objet enfreint évidemment les règles
d’emprunt, donc nous avons besoin d’un &lt;a href=&quot;https://doc.rust-lang.org/std/rc/&quot;&gt;pointeur à compteur de références&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cependant, un tel pointeur est en lecture seul, donc nous avons également besoin
d’un &lt;a href=&quot;https://doc.rust-lang.org/std/cell/index.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RefCell&lt;/code&gt;&lt;/a&gt; pour la &lt;a href=&quot;https://ricardomartins.cc/2016/06/08/interior-mutability&quot;&gt;&lt;em&gt;mutabilité intérieure&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ainsi, nous allons utiliser une instance de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;Storage&amp;gt;&amp;gt;&lt;/code&gt;. Cela peut
sembler trop verbeux, mais utiliser &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; (ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; pour
la &lt;em&gt;thread-safety&lt;/em&gt;) est très courant en Rust. Et &lt;a href=&quot;https://www.reddit.com/r/rust/comments/33jv62/vecrcrefcellboxtrait_is_there_a_better_way/&quot;&gt;il y a pire&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Voici ce que donne le code client :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RefCell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// first Rc to the Storage&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;RefCell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()));&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// second Rc to the Storage&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// register the listener saving all the received events to the Storage&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc2&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.borrow_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;141&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;141&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.borrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;De cette manière, le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt; est correctement modifié à partir de l’&lt;em&gt;event
listener&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Tout n’est pas résolu pour autant. Dans cet exemple, c’était facile, nous avions
accès à l’instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;Storage&amp;gt;&amp;gt;&lt;/code&gt;. Comment faire si nous avons seulement
accès au &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt;, par exemple si nous voulons que le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt; s’enregistre
lui-même à partir de l’une de ses méthodes, sans que l’appelant n’ait à fournir
l’instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;Storage&amp;gt;&amp;gt;&lt;/code&gt; ?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;register_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;cm&quot;&gt;/* how to retrieve a &amp;amp;mut Storage from here? */&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nous devons trouver un moyen de récupérer le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;Storage&amp;gt;&amp;gt;&lt;/code&gt; à partir du
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pour cela, l’idée consiste à rendre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt; conscient de son pointeur à
compteur de références. &lt;em&gt;Bien sûr, cela n’a du sens que si &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt; est
construit dans un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;Storage&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;C’est exactement ce que &lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/enable_shared_from_this&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enable_shared_from_this&lt;/code&gt;&lt;/a&gt; fournit en C++, donc nous
pouvons nous inspirer de &lt;a href=&quot;https://stackoverflow.com/a/34062114/1987178&quot;&gt;son fonctionnement&lt;/a&gt; : juste
stocker un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Weak&amp;lt;RefCell&amp;lt;…&amp;gt;&amp;gt;&lt;/code&gt;, &lt;a href=&quot;https://doc.rust-lang.org/std/rc/struct.Rc.html#method.downgrade&quot;&gt;&lt;em&gt;downgradé&lt;/em&gt;&lt;/a&gt; à partir du
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;…&amp;gt;&amp;gt;&lt;/code&gt;, dans la structure elle-même. De cette manière, nous pouvons
l’utiliser pour récupérer une référence &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut Storage&lt;/code&gt; à partir de l’&lt;em&gt;event
listener&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Weak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RefCell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self_weak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Weak&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RefCell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RefCell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;RefCell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;self_weak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Weak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// initialize empty&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// set self_weak once we get the Rc instance&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.borrow_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.self_weak&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;downgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;register_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.self_weak&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.upgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.borrow_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Voici comment l’utiliser :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Storage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.borrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.register_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;141&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;notifier&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.notify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;assert_eq!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;vec!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;141&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.borrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Il est donc possible d’implémenter le design pattern &lt;em&gt;observateur&lt;/em&gt; en Rust, mais
c’est un peu plus difficile qu’en Java ;-)&lt;/p&gt;

&lt;p&gt;Lorsque c’est possible, il est probablement préférable de l’éviter.&lt;/p&gt;

&lt;h3 id=&quot;partage-de-données-mutables&quot;&gt;Partage de données mutables&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mutable references cannot be &lt;a href=&quot;https://doc.rust-lang.org/nomicon/references.html&quot;&gt;aliased&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En français :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Les références mutables ne peuvent pas être &lt;a href=&quot;https://doc.rust-lang.org/nomicon/references.html&quot;&gt;aliasées&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Comment partager des données mutables, alors ?&lt;/p&gt;

&lt;p&gt;Nous avons vu que nous pouvions utiliser &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rc&amp;lt;RefCell&amp;lt;…&amp;gt;&amp;gt;&lt;/code&gt; (ou &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Arc&amp;lt;Mutex&amp;lt;…&amp;gt;&amp;gt;&lt;/code&gt;),
qui impose les règles d’emprunt à l’exécution. Cependant, ce n’est pas toujours
désirable :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;cela force une nouvelle allocation sur le tas,&lt;/li&gt;
  &lt;li&gt;chaque accès a un coût à l’exécution,&lt;/li&gt;
  &lt;li&gt;l’emprunt concerne toujours la ressource entière.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Au lieu de cela, nous pourrions utiliser des pointeurs &lt;em&gt;bruts&lt;/em&gt; manuellement dans
du code &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/unsafe.html&quot;&gt;non-sûr&lt;/a&gt;, mais alors ce serait &lt;em&gt;non-sûr&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Et il y a une autre solution, qui consiste à exposer des &lt;strong&gt;vues temporaires
d’emprunt&lt;/strong&gt; d’un objet. Laissez-moi expliquer.&lt;/p&gt;

&lt;p&gt;Dans &lt;em&gt;Gnirehtet&lt;/em&gt;, un paquet contient une référence vers les données brutes
(stockées dans un buffer quelque part) ainsi que les valeur des champs des
en-têtes &lt;a href=&quot;https://en.wikipedia.org/wiki/IPv4#Packet_structure&quot;&gt;IP&lt;/a&gt; et &lt;a href=&quot;https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure&quot;&gt;TCP&lt;/a&gt;/&lt;a href=&quot;https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure&quot;&gt;UDP&lt;/a&gt; (parsées à partir du tableau d’octets brut). Nous
aurions pu utiliser une structure à plat pour tout stocker :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Packet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ipv4_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ipv4_destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ipv4_protocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// + other ipv4 fields&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transport_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transport_destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// + other transport fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Packet&lt;/code&gt; aurait fourni des &lt;em&gt;setters&lt;/em&gt; pour tous les champs d’en-têtes
(modifiant à la fois les champs du paquet et le tableau d’octets). Par exemple :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Packet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set_transport_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transport_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.transport_source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transport_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transport&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;BigEndian&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write_u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transport&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais cette conception ne serait pas terrible (surtout que les champs d’en-têtes
TCP et UDP sont différents).&lt;/p&gt;

&lt;p&gt;À la place, nous voudrions extraire les en-têtes d’IP et de transport vers des
structures séparées, gérant leur propre partie du tableau d’octets :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// violates the borrowing rules&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Packet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// the whole packet (including headers)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ipv4_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4Header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transport_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4Header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// slice related to ipv4 headers&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// + other ipv4 fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// slice related to transport headers&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// + other transport fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Vous avez immédiatement repéré le problème : &lt;strong&gt;il y a plusieurs références vers
la même ressource, le tableau d’octets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt;, en même temps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Remarquez que &lt;a href=&quot;https://doc.rust-lang.org/std/primitive.slice.html#method.split_at_mut&quot;&gt;diviser&lt;/a&gt; le tableau n’est pas une possibilité ici, vu
que les slices de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; se chevauchent : nous avons besoin d’écrire le paquet
complet en une seule fois vers la couche réseau, donc le tableau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; dans
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Packet&lt;/code&gt; doit inclure les headers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nous avons besoin d’une solution compatible avec les règles d’emprunt.&lt;/p&gt;

&lt;p&gt;Voici celle à laquelle je suis parvenu :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;stocker les données des en-têtes séparément, sans les &lt;em&gt;slices&lt;/em&gt; de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;créer des structures de &lt;em&gt;vues&lt;/em&gt; pour les en-têtes d’IP et de transport, liées
à une &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/lifetimes.html#in-structs&quot;&gt;durée de vie&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;exposer des méthodes de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Packet&lt;/code&gt; retournant des instances de &lt;em&gt;vues&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Et voici une simplification de l’implémentation réelle :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Packet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ipv4_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4HeaderData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transport_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeaderData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4HeaderData&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// + other ipv4 fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeaderData&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// + other transport fields&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4Header&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4HeaderData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeaderData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Packet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ipv4_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ipv4Header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Ipv4Header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.ipv4_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transport_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TransportHeader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.transport_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Les &lt;em&gt;setters&lt;/em&gt; sont implémentés sur les vues, où ils détiennent une référence
mutable vers le tableau brut :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransportHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.data.source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;BigEndian&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write_u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set_destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.data.destination&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;BigEndian&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write_u16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;De cette manière, les règles d’emprunt sont respectées, et l’API est élégante :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// &quot;transport_header&quot; borrows &quot;packet&quot; during its scope&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transport_header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packet&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.transport_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transport_header&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.set_source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transport_header&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.set_destination&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;limitations-du-compilateur&quot;&gt;Limitations du compilateur&lt;/h3&gt;

&lt;p&gt;Rust est un langage jeune, et le compilateur a quelques problèmes ennuyeux.&lt;/p&gt;

&lt;p&gt;Le pire, d’après moi, est lié aux &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction/#problem-case-2-conditional-control-flow&quot;&gt;durées de vie non-lexicales&lt;/a&gt;, qui provoque des &lt;a href=&quot;https://stackoverflow.com/questions/44417491/non-lexical-lifetime-workaround-failure&quot;&gt;erreurs inattendues&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// we don&apos;t care the implementation&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.vec&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.vec&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.last_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error[E0499]: cannot borrow `self.vec` as mutable more than once at a time
  --&amp;gt; sample.rs:14:9
   |
11 |         if let Some(x) = self.find(v) {
   |                          ---- first mutable borrow occurs here
...
14 |         self.vec.push(v);
   |         ^^^^^^^^ second mutable borrow occurs here
15 |         self.vec.last_mut().unwrap()
16 |     }
   |     - first borrow ends here
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Heureusement, &lt;a href=&quot;http://smallcultfollowing.com/babysteps/blog/2017/07/11/non-lexical-lifetimes-draft-rfc-and-prototype-available/&quot;&gt;cela devrait être corrigé prochainement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La fonctionnalité d’&lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md&quot;&gt;&lt;em&gt;Impl Trait&lt;/em&gt;&lt;/a&gt;, permettant aux fonctions de
retourner des types abstraits &lt;em&gt;non-boxés&lt;/em&gt;, devrait aussi améliorer l’expérience
(il y a aussi une proposition &lt;a href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/1951-expand-impl-trait.md&quot;&gt;étendue&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Le compilateur produit généralement des messages d’erreur très utiles. Mais
quand ce n’est pas le cas, ils peuvent être très &lt;a href=&quot;https://stackoverflow.com/questions/44003622/implementing-trait-for-fnsomething-in-rust&quot;&gt;déroutants&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;sûreté-et-pièges&quot;&gt;Sûreté et pièges&lt;/h2&gt;

&lt;p&gt;Le &lt;a href=&quot;https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html&quot;&gt;premier chapitre du &lt;em&gt;Rustonomicon&lt;/em&gt;&lt;/a&gt; dit :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Safe Rust is For Reals Totally Safe.&lt;/p&gt;

  &lt;p&gt;[…]&lt;/p&gt;

  &lt;p&gt;Safe Rust is the true Rust programming language. If all you do is write Safe
Rust, you will never have to worry about type-safety or memory-safety. You
will never endure a null or dangling pointer, or any of that Undefined
Behavior nonsense.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En français :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;La partie Sûre de Rust est Réellement Totallement Sûre.&lt;/p&gt;

  &lt;p&gt;[…]&lt;/p&gt;

  &lt;p&gt;Le Rust Sûr est le vrai langage de programmation Rust. Si vous n’écrivez que
du Rust Sûr, vous n’aurez jamais à vous inquiétez de la sûreté des types ou de
la mémoire. Vous n’aurez jamais à supporter un pointeur null ou &lt;a href=&quot;https://fr.wikipedia.org/wiki/Dangling_pointer&quot;&gt;&lt;em&gt;dangling&lt;/em&gt;&lt;/a&gt;,
ou l’un de ces &lt;a href=&quot;/2014/10/comportement-indefini-et-optimisation/&quot;&gt;&lt;em&gt;comportements indéfinis&lt;/em&gt;&lt;/a&gt; insensés.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;C’est le but. Et c’est &lt;em&gt;presque&lt;/em&gt; vrai.&lt;/p&gt;

&lt;h3 id=&quot;leakpocalypse&quot;&gt;Leakpocalypse&lt;/h3&gt;

&lt;p&gt;Dans le passé, il a été &lt;a href=&quot;https://github.com/rust-lang/rust/issues/24292&quot;&gt;possible&lt;/a&gt; d’écrire du code &lt;em&gt;Rust sûr&lt;/em&gt;
&lt;strong&gt;accédant à de la mémoire libérée&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cette “&lt;a href=&quot;http://cglab.ca/~abeinges/blah/everyone-poops/&quot;&gt;leakpocalypse&lt;/a&gt;” a conduit à la &lt;a href=&quot;https://github.com/alexcrichton/rfcs/blob/safe-mem-forget/text/0000-safe-mem-forget.md&quot;&gt;clarification&lt;/a&gt; des guaranties
de sûreté : ne pas exécuter un destructeur est maintenant &lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1066&quot;&gt;considéré
&lt;em&gt;sûr&lt;/em&gt;&lt;/a&gt;. En d’autres termes, &lt;strong&gt;la sûreté mémoire ne peut plus
reposer sur &lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot;&gt;RAII&lt;/a&gt;&lt;/strong&gt; (en fait, elle n’a jamais pu, mais cela n’a été remarqué
que tardivement).&lt;/p&gt;

&lt;p&gt;En conséquence, &lt;a href=&quot;https://doc.rust-lang.org/std/mem/fn.forget.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::mem::forget&lt;/code&gt;&lt;/a&gt; est maintenant &lt;em&gt;sûr&lt;/em&gt;, et &lt;a href=&quot;https://doc.rust-lang.org/1.0.0/std/thread/struct.JoinGuard.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JoinGuard&lt;/code&gt;&lt;/a&gt; a
été déprécié et supprimé de la bibliothèque standard (il a été déplacé vers un
&lt;a href=&quot;http://arcnmx.github.io/thread-scoped-rs/thread_scoped/&quot;&gt;crate séparé&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Les autres outils s’appuyant sur RAII (comme &lt;a href=&quot;https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vec::drain()&lt;/code&gt;&lt;/a&gt;) doivent prendre
des &lt;a href=&quot;https://github.com/rust-lang/rust/blob/1.20.0/src/liballoc/vec.rs#L1094-L1102&quot;&gt;précautions particulières&lt;/a&gt; pour garantir que la mémoire
ne sera pas corrompue.&lt;/p&gt;

&lt;p&gt;Ouf, la &lt;em&gt;sûreté mémoire&lt;/em&gt; est (maintenant) sauvée.&lt;/p&gt;

&lt;h3 id=&quot;infinité-indéfinie&quot;&gt;Infinité indéfinie&lt;/h3&gt;

&lt;p&gt;En C et C++, les &lt;a href=&quot;https://stackoverflow.com/questions/3592557/optimizing-away-a-while1-in-c0x&quot;&gt;boucles infinies&lt;/a&gt; sans effets de bords sont un cas
d’&lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm&quot;&gt;&lt;em&gt;undefined behavior&lt;/em&gt;&lt;/a&gt;. À cause de cela, il est possible d’écrire des
programmes qui, de façon inattendue, &lt;a href=&quot;https://blog.regehr.org/archives/140&quot;&gt;réfutent le dernier théorème de
Fermat&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;En pratique, le compilateur Rust s’appuie sur LLVM, qui (actuellement) applique
ses optimisations en faisant l’hypothèse que les boucles infinies sans effets de
bords ont un &lt;em&gt;comportement indéfini&lt;/em&gt;. En conséquence, de tels &lt;em&gt;undefined
behaviors&lt;/em&gt; se produisent également en Rust.&lt;/p&gt;

&lt;p&gt;Voici un exemple minimal pour l’observer :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;infinite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;infinite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Quand on l’exécute sans optimisations, il se comporte comme “attendu” :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rustc ub.rs &amp;amp;&amp;amp; ./ub
^C                    (infinite loop, interrupt it)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mais activer les optimisations fait &lt;em&gt;paniquer&lt;/em&gt; le programme :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rustc -O ub.rs &amp;amp;&amp;amp; ./ub
thread &apos;main&apos; panicked at &apos;assertion failed: c.borrow().is_none()&apos;, /checkout/src/libstd/sys_common/thread_info.rs:51
note: Run with `RUST_BACKTRACE=1` for a backtrace.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nous pouvons aussi produire des résultats inattendus sans plantage :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;infinite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// infinite loop unless value initially equals 0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;infinite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;end&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rustc ub.rs &amp;amp;&amp;amp; ./ub
^C                    (infinite loop, interrupt it)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mais avec optimisations :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ rustc -O ub.rs &amp;amp;&amp;amp; ./ub
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;C’est un cas particulier, qui sera probablement corrigé dans le futur. En
pratique, &lt;strong&gt;les garanties de sûreté de Rust sont très fortes&lt;/strong&gt; (au prix d’être
contraignantes).&lt;/p&gt;

&lt;h3 id=&quot;erreur-de-segmentation&quot;&gt;Erreur de segmentation&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Cette section a été ajoutée après la publication.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Il y a d’autres sources d’&lt;em&gt;undefined behaviors&lt;/em&gt; (voir les &lt;a href=&quot;https://github.com/rust-lang/rust/labels/I-unsound&quot;&gt;&lt;em&gt;issues&lt;/em&gt; taggées
&lt;em&gt;I-unsound&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Par exemple, &lt;em&gt;caster&lt;/em&gt; une valeur flottante ne pouvant pas être représentée dans
le type cible est un &lt;em&gt;undefined behavior&lt;/em&gt;, qui peut être &lt;a href=&quot;https://github.com/rust-lang/rust/issues/10184#issuecomment-139858153&quot;&gt;propagé&lt;/a&gt; pour
provoquer une erreur de segmentation :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;nd&quot;&gt;#[inline(never)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1e100f64&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0xdeadbeef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rustc -O ub.rs &amp;amp;&amp;amp; ./ub
Erreur de segmentation
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;stats&quot;&gt;Stats&lt;/h2&gt;

&lt;p&gt;C’est tout pour mes retours sur le langage lui-même.&lt;/p&gt;

&lt;p&gt;En supplément, comparons les versions &lt;em&gt;Java&lt;/em&gt; et &lt;em&gt;Rust&lt;/em&gt; du serveur relais.&lt;/p&gt;

&lt;h3 id=&quot;nombre-de-lignes&quot;&gt;Nombre de lignes&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cloc relay-{java,rust}/src
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Rust                            29            687            655           4506
Java                            37            726            701           2931
-------------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(tests included)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Le projet Rust est significativement plus gros, pour plusieurs raisons :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;il y a beaucoup de classes de &lt;a href=&quot;#partage-de-donnes-mutables&quot;&gt;&lt;em&gt;vues d’emprunt&lt;/em&gt;&lt;/a&gt; ;&lt;/li&gt;
  &lt;li&gt;la version Rust définit sa propre classe de &lt;em&gt;selecteur&lt;/em&gt; d’I/O asynchrone,
encapsulant &lt;a href=&quot;https://docs.rs/mio/0.6.10/mio/struct.Poll.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Poll&lt;/code&gt;&lt;/a&gt; de plus bas niveau, alors que la version Java
utilise le &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/nio/channels/Selector.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Selector&lt;/code&gt;&lt;/a&gt; standard ;&lt;/li&gt;
  &lt;li&gt;la &lt;a href=&quot;https://doc.rust-lang.org/book/first-edition/error-handling.html&quot;&gt;gestion d’erreur&lt;/a&gt; pour l’analyse de la ligne de commande
est plus verbeuse.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La version Java contient plus de fichiers car les tests unitaires sont séparés,
alors qu’en Rust ils se trouvent dans le même fichier que les classes qu’ils
testent.&lt;/p&gt;

&lt;p&gt;Juste pour information, voici les résultats pour le client Android :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cloc app/src
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Java                            15            198            321            875
XML                              6              7              2             76
-------------------------------------------------------------------------------
SUM:                            21            205            323            951
-------------------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;taille-des-binaires&quot;&gt;Taille des binaires&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;--------------------------------------------
Java     gnirehtet.jar                   61K
--------------------------------------------
Rust     gnirehtet                      3.0M
         after &quot;strip -g gnirehtet&quot;     747K
         after &quot;strip gnirehtet&quot;        588K
--------------------------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Le binaire Java lui-même est bien plus petit. La comparaison n’est pas juste
cependant, vu qu’il nécessite l’&lt;em&gt;environnement d’exécution Java&lt;/em&gt; :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ du -sh /usr/lib/jvm/java-1.8.0-openjdk-amd64/
156M	/usr/lib/jvm/java-1.8.0-openjdk-amd64/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;utilisation-mémoire&quot;&gt;Utilisation mémoire&lt;/h3&gt;

&lt;p&gt;Avec une seule connection TCP ouvert, voici la consommation mémoire pour le
serveur relais en Java :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo pmap -x $RELAY_JAVA_PID
                  Kbytes     RSS   Dirty
total kB         4364052   86148   69316
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(résultat filtré)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Et pour le serveur relais en Rust :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo pmap -x $RELAY_RUST_PID
                  Kbytes     RSS   Dirty
total kB           19272    2736     640
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Regardez la valeur &lt;a href=&quot;https://en.wikipedia.org/wiki/Resident_set_size&quot;&gt;RSS&lt;/a&gt;, qui indique la mémoire réellement utilisée.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Comment on pouvait s’y attendre, la version Java consomme plus de mémoire
(86Mo) que la version Rust (moins de 3Mo). De plus, sa valeur est instable à
cause de l’allocation de petits objets et leur &lt;a href=&quot;https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)&quot;&gt;&lt;em&gt;garbage collection&lt;/em&gt;&lt;/a&gt;, qui
génère aussi davantage de &lt;em&gt;dirty pages&lt;/em&gt;. La valeur pour Rust, quant à elle, est
très stable : une fois la connection créée, il n’y a plus d’allocations mémoire
&lt;em&gt;du tout&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;utilisation-cpu&quot;&gt;Utilisation CPU&lt;/h3&gt;

&lt;p&gt;Pour comparer l’utilisation CPU, voici mon scénario : un fichier de 500Mo est
hébergé par Apache sur mon ordinateur, je démarre le serveur relais avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perf
stat&lt;/code&gt;, puis je télécharge le fichier à partir de Firefox sur Android. Dès que le
fichier est téléchargé, je stoppe le serveur relais (Ctrl+C).&lt;/p&gt;

&lt;p&gt;Voici les résultats pour la version Java :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ perf stat -B java -jar gnirehtet.jar relay
 Performance counter stats for &apos;java -jar gnirehtet.jar relay&apos;:

      11805,458302      task-clock:u (msec)       #    0,088 CPUs utilized
                 0      context-switches:u        #    0,000 K/sec
                 0      cpu-migrations:u          #    0,000 K/sec
            28 618      page-faults:u             #    0,002 M/sec
    17 908 360 446      cycles:u                  #    1,517 GHz
    13 944 172 792      stalled-cycles-frontend:u #   77,86% frontend cycles idle
    18 437 279 663      instructions:u            #    1,03  insn per cycle
                                                  #    0,76  stalled cycles per insn
     3 088 215 431      branches:u                #  261,592 M/sec
        70 647 760      branch-misses:u           #    2,29% of all branches

     133,975117164 seconds time elapsed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Et pour la version Rust :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ perf stat -B ./gnirehtet relay
 Performance counter stats for &apos;target/release/gnirehtet relay&apos;:

       2707,479968      task-clock:u (msec)       #    0,020 CPUs utilized
                 0      context-switches:u        #    0,000 K/sec
                 0      cpu-migrations:u          #    0,000 K/sec
             1 001      page-faults:u             #    0,370 K/sec
     1 011 527 340      cycles:u                  #    0,374 GHz
     2 033 810 378      stalled-cycles-frontend:u #  201,06% frontend cycles idle
       981 103 003      instructions:u            #    0,97  insn per cycle
                                                  #    2,07  stalled cycles per insn
        98 929 222      branches:u                #   36,539 M/sec
         3 220 527      branch-misses:u           #    3,26% of all branches

     133,766035253 seconds time elapsed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Je ne suis pas un expert pour analyser les résultats, mais de ce que je
comprends de la valeur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;task-clock:u&lt;/code&gt;, la version Rust consomme 4× moins de
temps CPU.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Réécrire &lt;em&gt;Gnirehtet&lt;/em&gt; en Rust a été une formidable expérience, où j’ai appris un
super langage et de nouveaux concepts de programmation. Et maintenant, nous
avons une application native avec de meilleures performances.&lt;/p&gt;

&lt;p&gt;Bon reverse tethering !&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Discussions sur &lt;a href=&quot;https://www.reddit.com/r/rust/comments/71ks57/gnirehtet_a_reverse_tethering_tool_for_android/&quot;&gt;reddit&lt;/a&gt; et &lt;a href=&quot;https://news.ycombinator.com/item?id=15326106&quot;&gt;Hacker News&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</content>
 </entry>
  
 
  
   
 <entry>
   <title>Fusionner deux dépôts git</title>
   <link href="https://blog.rom1v.com/2017/07/fusionner-deux-depots-git/"/>
   <updated>2017-07-12T20:30:00+02:00</updated>
   <id>https://blog.rom1v.com/2017/07/fusionner-deux-depots-git</id>
   <content type="html">&lt;p&gt;Ce billet explique comment fusionner un dépôt &lt;em&gt;git&lt;/em&gt; (avec son historique) dans
un sous-répertoire d’un autre dépôt &lt;em&gt;git&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;cas-dusage&quot;&gt;Cas d’usage&lt;/h2&gt;

&lt;p&gt;Mon projet principal se trouve dans un dépôt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;. J’ai démarré dans un autre
dépôt un projet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;other&lt;/code&gt;, que je souhaite finalement intégrer dans un
sous-répertoire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub/&lt;/code&gt; du projet principal, en conservant son historique. Après
cette fusion, je ne garderai que le dépôt principal.&lt;/p&gt;

&lt;h2 id=&quot;fusion&quot;&gt;Fusion&lt;/h2&gt;

&lt;p&gt;Les deux projets se trouvent dans le répertoire courant :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls
main  other
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dans le dépôt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;, &lt;em&gt;copier&lt;/em&gt; la branche &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;other&lt;/code&gt; dans une nouvelle
branche &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmp&lt;/code&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;main
git fetch ../other master:tmp&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le dépôt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; contient alors les historiques disjoints des deux projets.&lt;/p&gt;

&lt;p&gt;Nous allons maintenant réécrire l’historique complet de la branche &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmp&lt;/code&gt; pour
déplacer tout le contenu dans un sous-répertoire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub/&lt;/code&gt;, grâce une commande
donnée en exemple de &lt;a href=&quot;https://git-scm.com/docs/git-filter-branch#_examples&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man git filter-branch&lt;/code&gt;&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git checkout tmp
git filter-branch &lt;span class=&quot;nt&quot;&gt;--index-filter&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;git ls-files -s | sed &quot;s-\t\&quot;*-&amp;amp;sub/-&quot; |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
            git update-index --index-info &amp;amp;&amp;amp;
     mv &quot;$GIT_INDEX_FILE.new&quot; &quot;$GIT_INDEX_FILE&quot;&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;À ce stade, nous avons toujours deux historiques indépendants, mais le contenu
lié à la branche &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmp&lt;/code&gt; se trouve dans le sous-répertoire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sub/&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;A---B---C---D master

  X---Y---Z tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;La dernière étape consiste à relier les deux historiques, soit grâce à un
&lt;em&gt;rebase&lt;/em&gt;, soit grâce à un &lt;em&gt;merge&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Un &lt;em&gt;rebase&lt;/em&gt; réécrit l’historique du sous-projet sur la branche &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git rebase master

&lt;span class=&quot;c&quot;&gt;# A---B---C---D---X&apos;--Y&apos;--Z&apos; master&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Un &lt;em&gt;merge&lt;/em&gt; relie juste les deux historiques grâce à un commit de &lt;em&gt;merge&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git merge tmp &lt;span class=&quot;nt&quot;&gt;--allow-unrelated-histories&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# A---B---C---D---M  master&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#                /&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#       X---Y---Z tmp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;concrètement&quot;&gt;Concrètement&lt;/h2&gt;

&lt;p&gt;J’ai débuté la réécriture du serveur relais de &lt;a href=&quot;/2017/03/gnirehtet/&quot;&gt;gnirehtet&lt;/a&gt; en &lt;a href=&quot;https://www.rust-lang.org&quot;&gt;Rust&lt;/a&gt; dans un
dépôt séparé. Maintenant qu’il commence à fonctionner, je l’ai fusionné dans un
&lt;a href=&quot;https://github.com/Genymobile/gnirehtet/tree/rust/rustrelay&quot;&gt;sous-répertoire&lt;/a&gt; du &lt;a href=&quot;https://github.com/Genymobile/gnirehtet&quot;&gt;dépôt principal&lt;/a&gt; tout en conservant l’&lt;a href=&quot;https://github.com/Genymobile/gnirehtet/commits/rust&quot;&gt;historique&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git fetch ../rustrelay master:tmp
git checkout tmp
git filter-branch &lt;span class=&quot;nt&quot;&gt;--index-filter&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&apos;git ls-files -s | sed &quot;s-\t\&quot;*-&amp;amp;rustrelay/-&quot; |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
            git update-index --index-info &amp;amp;&amp;amp;
     mv &quot;$GIT_INDEX_FILE.new&quot; &quot;$GIT_INDEX_FILE&quot;&apos;&lt;/span&gt;
git rebase master&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
  
 
  
 
  
   
 <entry>
   <title>Gnirehtet</title>
   <link href="https://blog.rom1v.com/2017/03/gnirehtet/"/>
   <updated>2017-03-30T11:50:00+02:00</updated>
   <id>https://blog.rom1v.com/2017/03/gnirehtet</id>
   <content type="html">&lt;p&gt;Durant ces dernières semaines chez &lt;a href=&quot;https://www.genymobile.com/&quot;&gt;Genymobile&lt;/a&gt;, j’ai développé un outil de
&lt;em&gt;reverse tethering&lt;/em&gt; pour Android, permettant aux téléphones (et aux tablettes)
d’utiliser la connexion internet de l’ordinateur sur lequel ils sont branchés en
USB, sans accès &lt;em&gt;root&lt;/em&gt; (ni sur le téléphone, ni sur le PC). Il fonctionne sur
&lt;em&gt;GNU/Linux&lt;/em&gt;, &lt;em&gt;Windows&lt;/em&gt; et &lt;em&gt;Mac OS&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Nous avons décidé de le publier en open source, sous le nom de
&lt;a href=&quot;https://github.com/Genymobile/gnirehtet&quot;&gt;&lt;em&gt;gnirehtet&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Oui, c’est un nom bizarre, jusqu’à ce qu’on réalise qu’il s’agit du résultat de
la commande &lt;a href=&quot;https://fr.wikipedia.org/wiki/Bourne-Again_shell&quot;&gt;bash&lt;/a&gt; :&lt;/em&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;rev &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; tethering&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;utilisation&quot;&gt;Utilisation&lt;/h2&gt;

&lt;p&gt;Il suffit de télécharger la dernière &lt;a href=&quot;https://github.com/Genymobile/gnirehtet/releases/latest&quot;&gt;release&lt;/a&gt;, de l’extraire, et d’exécuter la
commande suivante sur le PC :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./gnirehtet rt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Une fois activé, un logo en forme de clé apparaît dans la barre de statut du
téléphone :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/gnirehtet/key.png&quot; alt=&quot;key&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Lisez le fichier &lt;a href=&quot;https://github.com/Genymobile/gnirehtet/blob/master/README.md&quot;&gt;README&lt;/a&gt; pour plus de détails.&lt;/p&gt;

&lt;h2 id=&quot;fonctionnement&quot;&gt;Fonctionnement&lt;/h2&gt;

&lt;p&gt;Le projet est composé de deux parties :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;une application Android (le client) ;&lt;/li&gt;
  &lt;li&gt;une application Java pour le PC (le serveur relais).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Depuis, &lt;a href=&quot;/2017/09/gnirehtet-reecrit-en-rust/&quot;&gt;je l’ai réécrit en Rust&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Le client s’enregistre en tant que VPN, de manière à intercepter tout le trafic
réseau du téléphone, sous la forme de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;byte[]&lt;/code&gt; de &lt;a href=&quot;https://en.wikipedia.org/wiki/IPv4#Packet_structure&quot;&gt;paquets IPv4&lt;/a&gt; bruts, qu’il
transmet alors vers le serveur relais sur une connexion &lt;a href=&quot;https://fr.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP&lt;/a&gt; (établie
par-dessus &lt;a href=&quot;https://developer.android.com/studio/command-line/adb.html&quot;&gt;&lt;em&gt;adb&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Le serveur relais analyse les en-têtes des paquets, ouvre des connexions à
partir du PC vers les adresses de destinations demandées, et relaie le contenu
dans les deux sens en suivant les protocoles &lt;a href=&quot;https://fr.wikipedia.org/wiki/User_Datagram_Protocol&quot;&gt;UDP&lt;/a&gt; et &lt;a href=&quot;https://fr.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP&lt;/a&gt;. Il crée et renvoie
des paquets de réponse vers le client Android, qui les écrit sur l’interface
VPN.&lt;/p&gt;

&lt;p&gt;D’une certaine manière, le serveur relais se comporte comme un &lt;a href=&quot;https://fr.wikipedia.org/wiki/Network_address_translation&quot;&gt;NAT&lt;/a&gt;, en cela
qu’il ouvre des connexions pour le compte d’autres machines qui n’ont pas accès
au réseau.  Cependant, il diffère des NAT standards dans la manière dont il
communique avec les clients, en utilisant un protocole spécifique (très simple)
sur une connexion TCP.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/gnirehtet/archi.png&quot; alt=&quot;archi&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pour plus de détails, lisez la &lt;a href=&quot;https://github.com/Genymobile/gnirehtet/blob/master/DEVELOP.md&quot;&gt;page développeurs&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conception&quot;&gt;Conception&lt;/h2&gt;

&lt;p&gt;Une fois que l’application est capable d’intercepter l’intégralité du traffic
réseau du téléphone, différentes approches sont possibles. Voici celles que j’ai
considérées.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; J’ai d’abord étudié l’utilisation d’un “TUN device” sur le
PC, mais ça ne répondait pas à nos besoins. J’ai ensuite voulu utiliser &lt;a href=&quot;https://fr.wikipedia.org/wiki/SOCKS&quot;&gt;SOCKS&lt;/a&gt;
pour bénéficier des serveurs existants, mais des contraintes nous empêchaient de
relayer le trafic UDP. Alors j’ai implémenté &lt;a href=&quot;https://github.com/Genymobile/gnirehtet&quot;&gt;gnirehtet&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;tun-device&quot;&gt;TUN device&lt;/h3&gt;

&lt;p&gt;Lors de mes recherches pour savoir comment implémenter le &lt;em&gt;reverse tethering&lt;/em&gt;,
j’ai d’abord trouvé des projets créant un &lt;a href=&quot;https://en.wikipedia.org/wiki/TUN/TAP&quot;&gt;TUN device&lt;/a&gt; sur l’ordinateur
(&lt;a href=&quot;https://github.com/google/vpn-reverse-tether&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vpn-reverse-tether&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/vvviperrr/SimpleRT&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleRT&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Cette conception fonctionne très bien, et a plusieurs avantages :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;le traitement est effectué directement au niveau réseau, donc il n’y a pas
besoin de traduction entre le niveau 3 et le niveau 5 du &lt;a href=&quot;https://fr.wikipedia.org/wiki/Mod%C3%A8le_OSI&quot;&gt;modèle OSI&lt;/a&gt; ;&lt;/li&gt;
  &lt;li&gt;tous les paquets sont retransmis, indépendamment de leur protocole de
transport (ils sont donc &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers&quot;&gt;tous&lt;/a&gt; supportés, là où &lt;em&gt;gnirehtet&lt;/em&gt;
ne supporte “que” &lt;a href=&quot;https://fr.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP&lt;/a&gt; et &lt;a href=&quot;https://fr.wikipedia.org/wiki/User_Datagram_Protocol&quot;&gt;UDP&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cependant :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;elle nécessite un accès &lt;em&gt;root&lt;/em&gt; sur l’ordinateur ;&lt;/li&gt;
  &lt;li&gt;elle ne fonctionne pas sur autre chose que &lt;em&gt;Linux&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il se peut néanmoins que ces applications répondent davantage à vos besoins.&lt;/p&gt;

&lt;h3 id=&quot;socks&quot;&gt;SOCKS&lt;/h3&gt;

&lt;p&gt;Afin d’éviter d’avoir à développer un serveur relais spécifique, ma première
idée était d’écrire un client qui parlait le protocole &lt;a href=&quot;https://fr.wikipedia.org/wiki/SOCKS&quot;&gt;SOCKS&lt;/a&gt; (suivant le &lt;a href=&quot;https://tools.ietf.org/html/rfc1928&quot;&gt;RFC
1928&lt;/a&gt;). Ainsi, il serait possible d’utiliser n’importe quel serveur SOCKS
existant, par exemple celui fourni par &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vous l’avez probablement déjà utilisé pour éviter le filtrage des pare-feux
en entreprise. Pour cela, démarrez le tunnel :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh mon_serveur -ND1080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Puis configurez votre navigateur pour utiliser le proxy SOCKS &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:1080&lt;/code&gt;.
N’oubliez pas d’activer la résolution DNS distante pour résoudre les noms de
domaine à partir de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mon_serveur&lt;/code&gt; (dans &lt;em&gt;Firefox&lt;/em&gt;, activez
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;network.proxy.socks_remote_dns&lt;/code&gt; dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;about:config&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Malheureusement, l’implémentation d’&lt;a href=&quot;https://fr.wikipedia.org/wiki/OpenSSH&quot;&gt;OpenSSH&lt;/a&gt; ne &lt;a href=&quot;http://lists.mindrot.org/pipermail/openssh-unix-dev/2017-January/035662.html&quot;&gt;supporte pas UDP&lt;/a&gt;,
même si le protocole &lt;a href=&quot;https://fr.wikipedia.org/wiki/SOCKS#SOCKS_v5&quot;&gt;SOCKS5&lt;/a&gt; lui-même le supporte. Et nous avons besoin d’UDP,
au moins pour les requêtes &lt;a href=&quot;https://fr.wikipedia.org/wiki/Domain_Name_System&quot;&gt;DNS&lt;/a&gt; (ainsi que pour &lt;a href=&quot;https://fr.wikipedia.org/wiki/Network_Time_Protocol&quot;&gt;NTP&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Si vous avez lu attentivement les deux paragraphes précédents, vous devriez vous
demander :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Comment Firefox peut-il résoudre les noms de domaine à distance alors
que le proxy SOCKS d’OpenSSH ne supporte même pas UDP ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La réponse se trouve dans la &lt;a href=&quot;https://tools.ietf.org/html/rfc1928#section-4&quot;&gt;section 4&lt;/a&gt; du RFC : l’adresse de destination
demandée peut être une IPv4, une IPv6 ou &lt;strong&gt;un nom de domaine&lt;/strong&gt;. Par contre,
pour utiliser cette fonctionnalité, le client (par exemple &lt;em&gt;Firefox&lt;/em&gt;) doit
savoir qu’il passe par un proxy (puisqu’il doit explicitement passer le nom de
domaine au lieu de le résoudre localement), alors que notre &lt;em&gt;reverse tethering&lt;/em&gt;
doit être &lt;strong&gt;transparent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mais tout n’est pas perdu. Certes, &lt;em&gt;OpenSSH&lt;/em&gt; ne supporte pas UDP, mais ce n’est
qu’une implémentation spécifique, nous pourrions en utiliser une autre.
Malheureusement, &lt;a href=&quot;http://stackoverflow.com/questions/41967217/why-does-socks5-require-to-relay-udp-over-udp&quot;&gt;SOCKS5 relaie UDP sur UDP&lt;/a&gt;, et les téléphones
et l’ordinateur communiquent sur &lt;em&gt;adb&lt;/em&gt; (grâce à &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb reverse&lt;/code&gt;), qui ne supporte
pas non plus la redirection de ports UDP.&lt;/p&gt;

&lt;p&gt;Peut-être que nous pourrions au moins relayer les requêtes DNS en les forçant à
&lt;a href=&quot;http://www.bortzmeyer.org/dns-over-tcp.html&quot;&gt;utiliser TCP&lt;/a&gt;, comme le fait &lt;a href=&quot;https://linux.die.net/man/8/tsocks&quot;&gt;tsocks&lt;/a&gt; :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;tsocks&lt;/strong&gt; will normally not be able to send DNS queries through a SOCKS
server since SOCKS V4 works on TCP and DNS normally uses UDP. Version 1.5 and
up do however provide a method to force DNS lookups to use TCP, which then
makes them proxyable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mais finalement, SOCKS n’est plus une solution aussi attirante pour implémenter
le &lt;em&gt;reverse tethering&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;gnirehtet&quot;&gt;Gnirehtet&lt;/h3&gt;

&lt;p&gt;Par conséquent, j’ai développé à la fois le client et le serveur relais
manuellement.&lt;/p&gt;

&lt;p&gt;Ce &lt;a href=&quot;http://www.thegeekstuff.com/2014/06/android-vpn-service/&quot;&gt;billet de blog&lt;/a&gt; et différents projets open source (&lt;a href=&quot;https://github.com/vvviperrr/SimpleRT&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleRT&lt;/code&gt;&lt;/a&gt;,
&lt;a href=&quot;https://github.com/google/vpn-reverse-tether&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vpn-reverse-tether&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/hexene/LocalVPN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalVPN&lt;/code&gt;&lt;/a&gt; et &lt;a href=&quot;https://android.googlesource.com/platform/development/+/master/samples/ToyVpn/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ToyVpn&lt;/code&gt;&lt;/a&gt;) m’ont beaucoup aidé à comprendre
comment implémenter cette solution de &lt;em&gt;reverse tethering&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Genymobile/gnirehtet&quot;&gt;&lt;em&gt;Gnirehtet&lt;/em&gt;&lt;/a&gt; permet aux téléphones et tablettes Android d’utiliser
facilement la connection internet d’un ordinateur par USB, sans accès &lt;em&gt;root&lt;/em&gt;.
C’est très utile quand vous ne pouvez pas accéder au réseau par un point d’accès
WiFi.&lt;/p&gt;

&lt;p&gt;J’espère qu’il pourra être utile à certains d’entre vous.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Discussions sur &lt;a href=&quot;https://www.reddit.com/r/Android/comments/62lc8z/a_reverse_tethering_tool_for_android_no_root/&quot;&gt;reddit&lt;/a&gt; et &lt;a href=&quot;https://news.ycombinator.com/item?id=14011590&quot;&gt;Hacker News&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</content>
 </entry>
  
 
  
   
 <entry>
   <title>Serveur-client</title>
   <link href="https://blog.rom1v.com/2017/03/serveur-client/"/>
   <updated>2017-03-12T23:17:12+01:00</updated>
   <id>https://blog.rom1v.com/2017/03/serveur-client</id>
   <content type="html">&lt;p&gt;L’objectif de ce billet est de parvenir à nous connecter à un serveur a priori
inaccessible derrière un &lt;a href=&quot;https://fr.wikipedia.org/wiki/Network_address_translation&quot;&gt;NAT&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;client-serveur&quot;&gt;Client-serveur&lt;/h2&gt;

&lt;p&gt;De nos jours, &lt;a href=&quot;https://fr.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;TCP&lt;/a&gt; est toujours utilisé en mode &lt;a href=&quot;https://fr.wikipedia.org/wiki/Client-serveur&quot;&gt;client-serveur&lt;/a&gt; :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;le &lt;strong&gt;serveur&lt;/strong&gt; écoute &lt;em&gt;passivement&lt;/em&gt; sur un &lt;a href=&quot;https://fr.wikipedia.org/wiki/Port_%28logiciel%29&quot;&gt;port&lt;/a&gt; donné, en attente de la
connexion d’un client ;&lt;/li&gt;
  &lt;li&gt;le &lt;strong&gt;client&lt;/strong&gt; initie &lt;em&gt;activement&lt;/em&gt; une connexion vers un serveur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une fois la connexion établie, cependant, le client et le serveur jouent
exactement le même rôle au niveau de la communication. Par contre, très souvent,
leur rôle applicatif dépend directement de celui qui a initié la connexion :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;c’est le &lt;strong&gt;client&lt;/strong&gt; &lt;a href=&quot;https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;HTTP&lt;/a&gt; qui va envoyer une requête au &lt;strong&gt;serveur&lt;/strong&gt; HTTP,
pas l’inverse ;&lt;/li&gt;
  &lt;li&gt;c’est le &lt;strong&gt;client&lt;/strong&gt; &lt;a href=&quot;https://fr.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; qui va ouvrir une session sur le &lt;strong&gt;serveur&lt;/strong&gt; SSH…&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/ssh.png&quot; alt=&quot;ssh&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ce fonctionnement paraît tellement naturel que “&lt;strong&gt;client&lt;/strong&gt;” désigne bien souvent
à la fois celui qui initie la connexion et celui qui effectue des requêtes (au
serveur), alors que “&lt;strong&gt;serveur&lt;/strong&gt;” désigne aussi bien la partie en écoute que
celle qui répondra aux requêtes (des clients).&lt;/p&gt;

&lt;h2 id=&quot;puis-vint-le-nat&quot;&gt;Puis vint le NAT…&lt;/h2&gt;

&lt;p&gt;Avec la &lt;a href=&quot;https://fr.wikipedia.org/wiki/%C3%89puisement_des_adresses_IPv4&quot;&gt;pénurie d’adresses IPv4&lt;/a&gt;, le NAT s’est généralisé. Bien
souvent, un accès internet ne fournit qu’une seule adresse &lt;a href=&quot;https://fr.wikipedia.org/wiki/IPv4&quot;&gt;IPv4&lt;/a&gt;. Les
différents ordinateurs partageant la même connexion ne sont alors pas
accessibles directement depuis l’extérieur (il est nécessaire d’&lt;a href=&quot;https://fr.wikipedia.org/wiki/Redirection_de_port&quot;&gt;ouvrir des
ports&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Ainsi, derrière un NAT sans ports ouverts, un &lt;strong&gt;serveur&lt;/strong&gt; ne sera pas accessible
publiquement. Par contre, un &lt;strong&gt;client&lt;/strong&gt; pourra continuer à se connecter à
n’importe quel serveur public.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/ssh-nat.png&quot; alt=&quot;ssh-nat&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;inversion-des-rôles&quot;&gt;Inversion des rôles&lt;/h2&gt;

&lt;p&gt;Il existe des situations pour lesquelles nous souhaitons qu’un logiciel joue le
rôle de &lt;strong&gt;serveur&lt;/strong&gt; au niveau applicatif, afin de répondre aux requêtes des
clients, mais &lt;strong&gt;client&lt;/strong&gt; au niveau de la communication, afin de passer les NATs
sans difficultés.&lt;/p&gt;

&lt;p&gt;Par exemple, nous pouvons vouloir accéder, grâce à &lt;a href=&quot;https://fr.wikipedia.org/wiki/Virtual_Network_Computing&quot;&gt;VNC&lt;/a&gt; ou SSH, à un
ordinateur se trouvant derrière un NAT sur lequel, par hypothèse, nous n’avons
pas la main. Dans ce cas, seul le &lt;strong&gt;serveur&lt;/strong&gt; (au sens applicatif) aura la
capacité d’ouvrir une connexion vers le &lt;strong&gt;client&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;logiciel-dédié&quot;&gt;Logiciel dédié&lt;/h3&gt;

&lt;p&gt;Il est possible d’utiliser un logiciel spécialement conçu pour gérer cette
inversion des rôles. C’est le cas par exemple de &lt;a href=&quot;https://doc.ubuntu-fr.org/gitso&quot;&gt;gitso&lt;/a&gt;, qui &lt;em&gt;inverse&lt;/em&gt; le
protocole VNC afin de simplifier l’aide de novices à distance.&lt;/p&gt;

&lt;p&gt;Cette solution a cependant l’inconvénient d’être très spécifique, nécessitant un
développement supplémentaire pour chaque protocole.&lt;/p&gt;

&lt;h3 id=&quot;redirection-de-port-distant-via-ssh&quot;&gt;Redirection de port distant via SSH&lt;/h3&gt;

&lt;p&gt;SSH permet d’ouvrir un tunnel pour rediriger un port d’une machine distance vers
une adresse quelconque.&lt;/p&gt;

&lt;p&gt;Par exemple, après avoir démarré la redirection :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh un_serveur_public -NR2222:localhost:22
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;toutes les connexions arrivant sur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;un_serveur_public:2222&lt;/code&gt; seront redirigées de
manière transparente vers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:22&lt;/code&gt; (sur la machine ayant initié le tunnel,
donc).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Cela nécessite d’activer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GatewayPorts yes&lt;/code&gt; dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/ssh/sshd_config&lt;/code&gt; sur
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;un_serveur_public&lt;/code&gt;.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;De cette manière, un serveur SSH inaccessible derrière un NAT est rendu
accessible à travers un tunnel en passant par une machine publique
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;un_serveur_public&lt;/code&gt;). Ainsi, il est possible de s’y connecter avec la
commande :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh un_serveur_public -p2222
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/ssh-remote.png&quot; alt=&quot;ssh-remote&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Cette stratégie fonctionne bien, mais elle nécessite que la machine qui souhaite
exposer un serveur grâce à un tunnel possède un accès SSH sur
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;un_serveur_public&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si l’on souhaite aider quelqu’un grâce à la prise de contrôle de sa machine à
distance, il y a toutes les chances que cette personne n’ait pas d’accès SSH
vers une machine publiquement accessible. Il est alors possible de lui &lt;a href=&quot;https://tuxicoman.jesuislibre.net/2015/03/aide-a-une-noob-par-reverse-ssh.html&quot;&gt;créer un
compte restreint dédié&lt;/a&gt; sur un serveur que l’on contrôle, mais c’est
très intrusif, et il faut s’assurer de ne pas réduire la sécurité.&lt;/p&gt;

&lt;p&gt;Mais en fait, &lt;strong&gt;cette contrainte est superflue&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;redirections-socat&quot;&gt;Redirections SOCAT&lt;/h3&gt;

&lt;p&gt;La redirection de port distant nécessite des permissions car, outre le fait
qu’elle est implémentée sur SSH, il serait déraisonnable d’autoriser n’importe
qui à ouvrir une &lt;a href=&quot;https://fr.wikipedia.org/wiki/Berkeley_sockets&quot;&gt;socket&lt;/a&gt; en écoute sur un port arbitraire d’une machine
distante.&lt;/p&gt;

&lt;p&gt;Pour éviter ce problème, nous pouvons décomposer la redirection de port distant
fourni par SSH en deux parties :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;l’ouverture de la connexion vers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;un_serveur_public&lt;/code&gt;, redirigée vers
l’adresse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:22&lt;/code&gt; dans l’exemple précédent ;&lt;/li&gt;
  &lt;li&gt;l’ouverture d’une socket en écoute sur un port (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2222&lt;/code&gt;) de la machine
distante, redirigée vers la première connexion.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;L’idée est de mettre en place le premier demi-tunnel sur la machine serveur, et
le second demi-tunnel, nécessitant des permissions, sur la machine publique,
contrôlée par le client.&lt;/p&gt;

&lt;p&gt;Pour cela, nous allons utiliser l’outil &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socat&lt;/code&gt;, qui permet de relayer les
données entre deux sockets, quelque soit le rôle qu’elles aient joué lors de
l’initialisation.&lt;/p&gt;

&lt;h4 id=&quot;active-passive&quot;&gt;Active-passive&lt;/h4&gt;

&lt;p&gt;Pour comprendre son utilisation, nous allons ouvrir grâce à &lt;em&gt;netcat&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nc&lt;/code&gt;) une
socket TCP en écoute sur le port &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5000&lt;/code&gt; et nous y connecter :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# terminal 1&lt;/span&gt;
nc &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 5000
&lt;span class=&quot;c&quot;&gt;# terminal 2&lt;/span&gt;
nc localhost 5000&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Toute entrée validée par un retour à la ligne dans le terminal 1 s’affichera
dans le terminal 2 (et vice-versa).&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/nc.png&quot; alt=&quot;nc&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;passive-passive&quot;&gt;Passive-passive&lt;/h4&gt;

&lt;p&gt;Démarrons maintenant dans deux terminaux différents une socket en écoute sur les
ports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1111&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2222&lt;/code&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# terminal 1&lt;/span&gt;
nc &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 1111
&lt;span class=&quot;c&quot;&gt;# terminal 2&lt;/span&gt;
nc &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 2222&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour les mettre en communication avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socat&lt;/code&gt;, dans un 3e terminal :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;socat tcp:localhost:1111 tcp:localhost:2222
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/socat-connect.png&quot; alt=&quot;socat-connect&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;active-active&quot;&gt;Active-active&lt;/h4&gt;

&lt;p&gt;Inversement, il est possible de mettre en communication deux sockets &lt;em&gt;actives&lt;/em&gt;
(sans compter sur leur &lt;a href=&quot;http://linuxfr.org/users/benoar/journaux/syn-c-est-pour-synchronisation&quot;&gt;synchronisation&lt;/a&gt;). Pour cela, commençons par ouvrir
le serveur relai :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;socat tcp-listen:1111 tcp-listen:2222
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Puis connectons-y deux sockets :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# terminal 1&lt;/span&gt;
nc localhost 1111
&lt;span class=&quot;c&quot;&gt;# terminal 2&lt;/span&gt;
nc localhost 2222&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/socat-listen.png&quot; alt=&quot;socat-connect&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;tunnel&quot;&gt;Tunnel&lt;/h4&gt;

&lt;p&gt;Nous sommes maintenant prêts pour créer l’équivalent d’une redirection de port
distant SSH grâce à deux &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socat&lt;/code&gt;s, qui vont permettre d’inverser la connexion
uniquement sur la portion qui permet de traverser le NAT :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# sur un_serveur_public&lt;/span&gt;
socat tcp-listen:1234 tcp-listen:5678
&lt;span class=&quot;c&quot;&gt;# sur le serveur derrière le NAT&lt;/span&gt;
socat tcp:un_serveur_public:1234 tcp:localhost:22
&lt;span class=&quot;c&quot;&gt;# sur le client&lt;/span&gt;
ssh un_serveur_public &lt;span class=&quot;nt&quot;&gt;-p5678&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/serveur_client/ssh-socat.png&quot; alt=&quot;ssh-socat&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
  
 
  
   
 <entry>
   <title>SHAdow</title>
   <link href="https://blog.rom1v.com/2017/03/shadow/"/>
   <updated>2017-03-01T01:00:00+01:00</updated>
   <id>https://blog.rom1v.com/2017/03/shadow</id>
   <content type="html">&lt;p&gt;Le 23 février, une équipe de chercheurs a &lt;a href=&quot;https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html&quot;&gt;annoncé&lt;/a&gt; avoir cassé &lt;a href=&quot;https://en.wikipedia.org/wiki/SHA-1&quot;&gt;SHA-1&lt;/a&gt; &lt;a href=&quot;http://shattered.io/&quot;&gt;en
pratique&lt;/a&gt;, en générant une &lt;a href=&quot;https://en.wikipedia.org/wiki/Collision_attack&quot;&gt;collision&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;À partir de leur travail, il est possible de produire de nouvelles paires de
fichiers PDF arbitrairement différents qui auront la même signature SHA-1. Par
exemple :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;a href=&quot;/assets/shadow/shadow1.pdf&quot;&gt;&lt;img src=&quot;/assets/shadow/tux.jpg&quot; alt=&quot;shadow1-thumb&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;/assets/shadow/shadow2.pdf&quot;&gt;&lt;img src=&quot;/assets/shadow/troll.jpg&quot; alt=&quot;shadow2-thumb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sha1sum shadow1.pdf shadow2.pdf
fffe36a1d6f0a76a585af4f3838a4a46b6714f0c  shadow1.pdf
fffe36a1d6f0a76a585af4f3838a4a46b6714f0c  shadow2.pdf
$ sha256sum shadow1.pdf shadow2.pdf
502ccf8ecee10176d891fa4aeab295edec22b95141c2ae16d85f13b39879e37e  shadow1.pdf
2546d272df653c5a99ef0914fa6ed43b336f309758ea873448154ebde90cdfe1  shadow2.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;J’explique dans ce billet le principe, et je fournis un outil qui produit, à
partir de deux images JPEG, deux fichiers PDF différents de même SHA-1.&lt;/p&gt;

&lt;h2 id=&quot;réutilisation&quot;&gt;Réutilisation&lt;/h2&gt;

&lt;p&gt;En fabriquant leur collision, les &lt;a href=&quot;https://shattered.io/static/shattered.pdf&quot;&gt;auteurs&lt;/a&gt; ont pris soin de la rendre
réutilisable :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Furthermore, the prefix of the colliding messages was carefully chosen so that
they allow an attacker to forge two PDF documents with the same SHA-1 hash yet
that display arbitrarily-chosen distinct visual content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aujourd’hui, nous allons jouer aux attaquants.&lt;/p&gt;

&lt;p&gt;La réutilisation de la collision repose sur le fait qu’avec SHA-1, ajouter un
suffixe identique à une collision existante produit encore une collision :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SHA1(A) == SHA1(B) ==&amp;gt; SHA1(A|X) == SHA1(B|X)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(où &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X|Y&lt;/code&gt; est la concaténation de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt; et de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Y&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Autrement dit, vous prenez les fichiers qui produisent une collision, vous
ajoutez les mêmes octets aux deux, vous obtenez le même SHA-1 :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ { cat shattered-1.pdf; echo bonjour; } | sha1sum
4bfd4b804da3aa207b29d6f1300dde507988dc4b  -
$ { cat shattered-2.pdf; echo bonjour; } | sha1sum
4bfd4b804da3aa207b29d6f1300dde507988dc4b  -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Il est donc trivial de créer de &lt;em&gt;nouvelles&lt;/em&gt; collisions.&lt;/p&gt;

&lt;p&gt;Mais pour qu’elles aient un intérêt, encore faut-il :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;que les fichiers produits soient valides ;&lt;/li&gt;
  &lt;li&gt;qu’une différence entre les fichiers soit visible par l’utilisateur.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;différences&quot;&gt;Différences&lt;/h2&gt;

&lt;p&gt;Les différences entre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shattered-1.pdf&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shattered-2.pdf&lt;/code&gt; se situent entre
les adresses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xc0&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x13f&lt;/code&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;diff &lt;span class=&quot;nt&quot;&gt;-U3&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;hd shattered-1.pdf&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;hd shattered-2.pdf&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;gd&quot;&gt;--- /dev/fd/63  2017-02-28 21:11:11.530135134 +0100
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ /dev/fd/62  2017-02-28 21:11:11.530135134 +0100
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -10,14 +10,14 @@&lt;/span&gt;
 00000090  72 65 61 6d 0a ff d8 ff  fe 00 24 53 48 41 2d 31  |ream......$SHA-1|
 000000a0  20 69 73 20 64 65 61 64  21 21 21 21 21 85 2f ec  | is dead!!!!!./.|
 000000b0  09 23 39 75 9c 39 b1 a1  c6 3c 4c 97 e1 ff fe 01  |.#9u.9...&amp;lt;L.....|
&lt;span class=&quot;gd&quot;&gt;-000000c0  73 46 dc 91 66 b6 7e 11  8f 02 9a b6 21 b2 56 0f  |sF..f.~.....!.V.|
-000000d0  f9 ca 67 cc a8 c7 f8 5b  a8 4c 79 03 0c 2b 3d e2  |..g....[.Ly..+=.|
-000000e0  18 f8 6d b3 a9 09 01 d5  df 45 c1 4f 26 fe df b3  |..m......E.O&amp;amp;...|
-000000f0  dc 38 e9 6a c2 2f e7 bd  72 8f 0e 45 bc e0 46 d2  |.8.j./..r..E..F.|
-00000100  3c 57 0f eb 14 13 98 bb  55 2e f5 a0 a8 2b e3 31  |&amp;lt;W......U....+.1|
-00000110  fe a4 80 37 b8 b5 d7 1f  0e 33 2e df 93 ac 35 00  |...7.....3....5.|
-00000120  eb 4d dc 0d ec c1 a8 64  79 0c 78 2c 76 21 56 60  |.M.....dy.x,v!V`|
-00000130  dd 30 97 91 d0 6b d0 af  3f 98 cd a4 bc 46 29 b1  |.0...k..?....F).|
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+000000c0  7f 46 dc 93 a6 b6 7e 01  3b 02 9a aa 1d b2 56 0b  |.F....~.;.....V.|
+000000d0  45 ca 67 d6 88 c7 f8 4b  8c 4c 79 1f e0 2b 3d f6  |E.g....K.Ly..+=.|
+000000e0  14 f8 6d b1 69 09 01 c5  6b 45 c1 53 0a fe df b7  |..m.i...kE.S....|
+000000f0  60 38 e9 72 72 2f e7 ad  72 8f 0e 49 04 e0 46 c2  |`8.rr/..r..I..F.|
+00000100  30 57 0f e9 d4 13 98 ab  e1 2e f5 bc 94 2b e3 35  |0W...........+.5|
+00000110  42 a4 80 2d 98 b5 d7 0f  2a 33 2e c3 7f ac 35 14  |B..-....*3....5.|
+00000120  e7 4d dc 0f 2c c1 a8 74  cd 0c 78 30 5a 21 56 64  |.M..,..t..x0Z!Vd|
+00000130  61 30 97 89 60 6b d0 bf  3f 98 cd a8 04 46 29 a1  |a0..`k..?....F).|
&lt;/span&gt; 00000140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 *
 00000230  00 00 ff fe 00 fc 00 00  00 00 00 00 00 00 ff e0  |................|&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nous devrons donc, quoi qu’il arrive, conserver les &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x140&lt;/code&gt; (320) premiers
octets : il s’agira forcément d’un fichier PDF.&lt;/p&gt;

&lt;p&gt;Pour analyser la structure sur un exemple minimal, je vous conseille l’exemple
fourni à la dernière page du &lt;a href=&quot;https://shattered.io/static/shattered.pdf&quot;&gt;papier&lt;/a&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;good.pdf&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bad.pdf&lt;/code&gt;) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;&amp;lt; -- base64 -d | tar xj
QlpoOTFBWSZTWbL5V5MABl///////9Pv///v////+/////HDdK739/677r+W3/75rUNr4Aa/AAAAAAA
CgEVTRtQDQAaA0AAyGmjTQGmgAAANGgAaMIAYgGgAABo0AAAAAADQAIAGQ0MgDIGmjQA0DRk0AaMQ0D
QAGIANGgAAGRoNGQMRpo0GIGgBoGQAAIAGQ0MgDIGmjQA0DRk0AaMQ0DQAGIANGgAAGRoNGQMRpo0GI
GgBoGQAAIAGQ0MgDIGmjQA0DRk0AaMQ0DQAGIANGgAAGRoNGQMRpo0GIGgBoGQAAIAGQ0MgDIGmjQA0
DRk0AaMQ0DQAGIANGgAAGRoNGQMRpo0GIGgBoGQAABVTUExEZATTICnkxNR+p6E09JppoyamjGhkm0a
mmIyaekbUejU9JiGnqZqaaDxJ6m0JkZMQ2oaYmJ6gxqMyE2TUzJqfItligtJQJfYbl9Zy9QjQuB5mHQ
RdSSXCCTHMgmSDYmdOoOmLTBJWiCpOhMQYpQlOYpJjn+wQUJSTCEpOMekaFaaNB6glCC0hKEJdHr6Bm
UIHeph7YxS8WJYyGwgWnMTFJBDFSxSCCYljiEk7HZgJzJVDHJxMgY6tCEIIWgsKSlSZ0S8GckoIIF+5
51Ro4RCw260VCEpWJSlpWx/PMrLyVoyhWMAneDilBcUIeZ1j6NCkus0qUCWnahhk5KT4GpWMh3vm2nJ
WjTL9Qg+84iExBJhNKpbV9tvEN265t3fu/TKkt4rXFTsV+NcupJXhOhOhJMQQktrqt4K8mSh9M2DAO2
X7uXGVL9YQxUtzQmS7uBndL7M6R7vX869VxqPurenSuHYNq1yTXOfNWLwgvKlRlFYqLCs6OChDp0HuT
zCWscmGudLyqUuwVGG75nmyZhKpJyOE/pOZyHyrZxGM51DYIN+Jc8yVJgAykxKCEtW55MlfudLg3KG6
TtozalunXrroSxUpVLStWrWLFihMnVpkyZOrQnUrE6xq1CGtJlbAb5ShMbV1CZgqlKC0wCFCpMmUKSE
kvFLaZC8wHOCVAlvzaJQ/T+XLb5Dh5TNM67p6KZ4e4ZSGyVENx2O27LzrTIteAreTkMZpW95GS0CEJY
hMc4nToTJ0wQhKEyddaLb/rTqmgJSlkpnALxMhlNmuKEpkEkqhKUoEq3SoKUpIQcDgWlC0rYahMmLuP
Q0fHqZaF4v2W8IoJ2EhMhYmSw7qql27WJS+G4rUplToFi2rSv0NSrVvDUpltQ8Lv6F8pXyxmFBSxiLS
xglNC4uvXVKmAtusXy4YXGX1ixedEvXF1aX6t8adYnYCpC6rW1ZzdZYlCCxKEv8vpbqdSsXl8v1jCQv
0KEPxPTa/5rtWSF1dSgg4z4KjfIMNtgwWoWLEsRhKxsSA9ji7V5LRPwtumeQ8V57UtFSPIUmtQdOQfs
eI2Ly1DMtk4Jl8n927w34zrWG6Pi4jzC82js/46Rt2IZoadWxOtMInS2xYmcu8mOw9PLYxQ4bdfFw3Z
Pf/g2pzSwZDhGrZAl9lqky0W+yeanadC037xk496t0Dq3ctfmqmjgie8ln9k6Q0K1krb3dK9el4Xsu4
4LpGcenr2eQZ1s1IhOhnE56WnXf0BLWn9Xz15fMkzi4kpVxiTKGEpffErEEMvEeMZhUl6yD1SdeJYbx
zGNM3ak2TAaglLZlDCVnoM6wV5DRrycwF8Zh/fRsdmhkMfAO1duwknrsFwrzePWeMwl107DWzymxdQw
iSXx/lncnn75jL9mUzw2bUDqj20LTgtawxK2SlQg1CCZDQMgSpEqLjRMsykM9zbSIUqil0zNk7Nu+b5
J0DKZlhl9CtpGKgX5uyp0idoJ3we9bSrY7PupnUL5eWiDpV5mmnNUhOnYi8xyClkLbNmAXyoWk7GaVr
M2umkbpqHDzDymiKjetgzTocWNsJ2E0zPcfht46J4ipaXGCfF7fuO0a70c82bvqo3HceIcRlshgu73s
eO8BqlLIap2z5jTOY+T2ucCnBtAtva3aHdchJg9AJ5YdKHz7LoA3VKmeqxAlFyEnQLBxB2PAhAZ8Kvm
uR6ELXws1Qr13Nd1i4nsp189jqvaNzt+0nEnIaniuP1+/UOZdyfoZh57ku8sYHKdvfW/jYSUks+0rK+
qtte+py8jWL9cOJ0fV8rrH/t+85/p1z2N67p/ZsZ3JmdyliL7lrNxZUlx0MVIl6PxXOUuGOeArW3vuE
vJ2beoh7SGyZKHKbR2bBWO1d49JDIcVM6lQtu9UO8ec8pOnXmkcponBPLNM2CwZ9kNC/4ct6rQkPkQH
McV/8XckU4UJCy+VeTA==
--
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;aiguillage&quot;&gt;Aiguillage&lt;/h2&gt;

&lt;p&gt;Notre objectif est que les quelques octets différents entre les deux fichiers
PDF déterminent l’image à afficher.&lt;/p&gt;

&lt;p&gt;Il serait en théorie possible d’appliquer cet aiguillage au niveau de la
structure du PDF, mais c’est en fait au niveau du JPEG qu’il sera implémenté :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;PDFs with the same MD5 hash have previously been constructed by Gebhardt et
al. [&lt;a href=&quot;http://csrc.nist.gov/groups/ST/hash/documents/Illies_NIST_05.pdf&quot;&gt;12&lt;/a&gt;] by exploiting so-called Indexed Color Tables and Color Transformation
functions. However, this method is not effective for many common PDF viewers
that lack support for these functionalities.  Our PDFs rely on distinct
parsings of JPEG images, similar to Gebhardt et al.’s TIFF technique
[&lt;a href=&quot;http://csrc.nist.gov/groups/ST/hash/documents/Illies_NIST_05.pdf&quot;&gt;12&lt;/a&gt;] and Albertini et al.’s JPEG technique [&lt;a href=&quot;http://dx.doi.org/10.1007/978-3-319-13051-4_1&quot;&gt;1&lt;/a&gt;].&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;le-format-jpeg&quot;&gt;Le format JPEG&lt;/h3&gt;

&lt;p&gt;Voici le strict nécessaire à savoir sur le format JPEG pour notre besoin.&lt;/p&gt;

&lt;p&gt;Une image est stockée entre les &lt;a href=&quot;https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure&quot;&gt;marqueurs&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xffd8&lt;/code&gt; (&lt;em&gt;Start Of Image&lt;/em&gt;) et
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xffd9&lt;/code&gt; (&lt;em&gt;End Of Image&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Il est possible d’insérer autant de commentaires que l’on veut, grâce au
marqueur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xfffe&lt;/code&gt; suivi de sa taille sur 2 octets (en &lt;a href=&quot;https://en.wikipedia.org/wiki/Endianness&quot;&gt;big-endian&lt;/a&gt;). La taille
compte le header de taille, mais pas le marqueur initial.&lt;/p&gt;

&lt;p&gt;Par exemple, si je veux insérer le commentaire &lt;em&gt;“Hello”&lt;/em&gt; au tout début, mon
fichier JPEG ressemblera à ceci :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ff d8 ff fe 00 07 48 65 6c 6c 6f  …  ff d9
 [SOI]                                [EOI]
      [[COM] [LEN]  H  e  l  l  o]
             &amp;lt;-------------------&amp;gt;
                       7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Et c’est à peu près tout ce qu’il y a à savoir.&lt;/p&gt;

&lt;h3 id=&quot;lastuce&quot;&gt;L’astuce&lt;/h3&gt;

&lt;p&gt;Mettons en évidence la première différence entre les fichiers en collision.&lt;/p&gt;

&lt;p&gt;Dans le &lt;strong&gt;fichier 1&lt;/strong&gt; :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;000000b0  -- -- -- -- -- -- -- --  -- -- -- -- -- ff fe 01
000000c0  73 -- -- -- -- -- -- --  -- -- -- -- -- -- -- --
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dans le &lt;strong&gt;fichier 2&lt;/strong&gt; :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;000000b0  -- -- -- -- -- -- -- --  -- -- -- -- -- ff fe 01
000000c0  7f -- -- -- -- -- -- --  -- -- -- -- -- -- -- --
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Chacun définit un bloc de commentaires, mais pas de mêmes tailles. Dans le
fichier 1, le début du prochain bloc sera à l’adresse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x232&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xbf + 0x173&lt;/code&gt;),
alors que dans le fichier 2 il sera à l’adresse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x23e&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xbf + 0x17f&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Nous avons donc trouvé notre aiguillage ; nous allons maintenant utiliser des
commentaires JPEG pour cacher soit la première image, soit la seconde.&lt;/p&gt;

&lt;p&gt;Pour l’exploiter jusqu’au bout, il suffit de disposer les commentaires
astucieusement pour que les deux versions représentent des images parfaitement
valides.&lt;/p&gt;

&lt;p&gt;Nous allons donc commencer en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x232&lt;/code&gt; un bloc de commentaires, ayant une taille
permettant de recouvrir l’intégralité de l’image que nous allons stocker en
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x23e&lt;/code&gt;. Et inversement, nous devons démarrer un commentaire à la fin de l’image
stockée en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x23e&lt;/code&gt; pour cacher la deuxième image.&lt;/p&gt;

&lt;p&gt;Comparons sur le résultat ce qu’observe un &lt;em&gt;parseur&lt;/em&gt; qui parcourt chacun des
fichiers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GG&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HH&lt;/code&gt; sont les deux images à stocker. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;J1&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;J2&lt;/code&gt; sont les longueurs
des sauts pour enjamber chacune des images.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Le &lt;strong&gt;fichier 1&lt;/strong&gt; est &lt;em&gt;parsé&lt;/em&gt; ainsi :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
00000090  -- -- -- -- -- &lt;strong&gt;ff d8&lt;/strong&gt; --  -- -- -- -- -- -- -- --
       …
000000b0  -- -- -- -- -- -- -- --  -- -- -- -- -- &lt;span style=&quot;color: blue;&quot;&gt;ff fe 01&lt;/span&gt;
000000c0  &lt;span style=&quot;color: blue;&quot;&gt;73 -- -- -- -- -- -- --  -- -- -- -- -- -- -- --&lt;/span&gt;
       …
00000230  &lt;span style=&quot;color: blue;&quot;&gt;-- --&lt;/span&gt; &lt;span style=&quot;color: green;&quot;&gt;ff fe J1 J1 -- --  -- -- -- -- -- -- GG GG&lt;/span&gt;
00000240  &lt;span style=&quot;color: green;&quot;&gt;GG GG GG GG GG GG GG GG  GG GG GG GG GG GG GG GG&lt;/span&gt;
       …
       i  &lt;span style=&quot;color: green;&quot;&gt;GG GG GG GG GG GG ff fe  J2 J2&lt;/span&gt; &lt;span style=&quot;color: red;&quot;&gt;HH HH HH HH HH HH&lt;/span&gt;
  i+0x10  &lt;span style=&quot;color: red;&quot;&gt;HH HH HH HH HH HH HH HH  HH HH HH HH HH HH HH HH&lt;/span&gt;
       …
       j  &lt;span style=&quot;color: red;&quot;&gt;HH HH&lt;/span&gt; &lt;strong&gt;ff d9&lt;/strong&gt; -- -- -- --  -- -- -- -- -- -- -- --
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Le &lt;strong&gt;fichier 2&lt;/strong&gt; est &lt;em&gt;parsé&lt;/em&gt; différemment :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
00000090  -- -- -- -- -- &lt;strong&gt;ff d8&lt;/strong&gt; --  -- -- -- -- -- -- -- --
       …
000000b0  -- -- -- -- -- -- -- --  -- -- -- -- -- &lt;span style=&quot;color: blue;&quot;&gt;ff fe 01&lt;/span&gt;
000000c0  &lt;span style=&quot;color: blue;&quot;&gt;7f -- -- -- -- -- -- --  -- -- -- -- -- -- -- --&lt;/span&gt;
       …
00000230  &lt;span style=&quot;color: blue;&quot;&gt;-- -- ff fe J1 J1 -- --  -- -- -- -- -- --&lt;/span&gt; &lt;span style=&quot;color: red;&quot;&gt;GG GG&lt;/span&gt;
00000240  &lt;span style=&quot;color: red;&quot;&gt;GG GG GG GG GG GG GG GG  GG GG GG GG GG GG GG GG&lt;/span&gt;
       …
       i  &lt;span style=&quot;color: red;&quot;&gt;GG GG GG GG GG GG&lt;/span&gt; &lt;span style=&quot;color: green;&quot;&gt;ff fe  J2 J2 HH HH HH HH HH HH&lt;/span&gt;
  i+0x10  &lt;span style=&quot;color: green;&quot;&gt;HH HH HH HH HH HH HH HH  HH HH HH HH HH HH HH HH&lt;/span&gt;
       …
       j  &lt;span style=&quot;color: green;&quot;&gt;HH HH&lt;/span&gt; &lt;strong&gt;ff d9&lt;/strong&gt; -- -- -- --  -- -- -- -- -- -- -- --
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Les structures JPEG sont donc valides dans les deux fichiers. L’image affichée
dépendra de l’octet stocké à l’adresse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xc0&lt;/code&gt;, valant soit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x73&lt;/code&gt;, soit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Maintenant, il nous reste à rendre notre PDF valide.&lt;/p&gt;

&lt;h2 id=&quot;pdf&quot;&gt;PDF&lt;/h2&gt;

&lt;p&gt;Le header participant à la collision SHA-1 (donc figé) définit des
configurations dans des &lt;em&gt;sections&lt;/em&gt; séparées (donc non figées) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;00000000  25 50 44 46 2d 31 2e 33  0a 25 e2 e3 cf d3 0a 0a  |%PDF-1.3.%......|
00000010  0a 31 20 30 20 6f 62 6a  0a 3c 3c 2f 57 69 64 74  |.1 0 obj.&amp;lt;&amp;lt;/Widt|
00000020  68 20 32 20 30 20 52 2f  48 65 69 67 68 74 20 33  |h 2 0 R/Height 3|
00000030  20 30 20 52 2f 54 79 70  65 20 34 20 30 20 52 2f  | 0 R/Type 4 0 R/|
00000040  53 75 62 74 79 70 65 20  35 20 30 20 52 2f 46 69  |Subtype 5 0 R/Fi|
00000050  6c 74 65 72 20 36 20 30  20 52 2f 43 6f 6c 6f 72  |lter 6 0 R/Color|
00000060  53 70 61 63 65 20 37 20  30 20 52 2f 4c 65 6e 67  |Space 7 0 R/Leng|
00000070  74 68 20 38 20 30 20 52  2f 42 69 74 73 50 65 72  |th 8 0 R/BitsPer|
00000080  43 6f 6d 70 6f 6e 65 6e  74 20 38 3e 3e 0a 73 74  |Component 8&amp;gt;&amp;gt;.st|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ainsi, la largeur (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Width&lt;/code&gt;) est définie dans l’objet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;, la hauteur (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Height&lt;/code&gt;)
dans l’objet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Ces objets sont à définir à la suite des fichiers JPEG embarqués. Pour
comprendre leur format, le plus simple est de lire le fichier &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;good.pdf&lt;/code&gt; que je
recommandais plus haut :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;+&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;x746&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt; good.pdf&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;On y trouve la définition des objets (entre autres les dimensions de l’image) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2 0 obj
8
endobj

3 0 obj
8
endobj

4 0 obj
/XObject
endobj

5 0 obj
/Image
endobj

6 0 obj
/DCTDecode
endobj

7 0 obj
/DeviceRGB
endobj

8 0 obj
1693
endobj

9 0 obj
&amp;lt;&amp;lt;
  /Type /Catalog
  /Pages 10 0 R
&amp;gt;&amp;gt;
endobj


10 0 obj
&amp;lt;&amp;lt;
  /Type /Pages
  /Count 1
  /Kids [11 0 R]
&amp;gt;&amp;gt;
endobj

11 0 obj
&amp;lt;&amp;lt;
  /Type /Page
  /Parent 10 0 R
  /MediaBox [0 0 8 8]
  /CropBox [0 0 8 8]
  /Contents 12 0 R
  /Resources
  &amp;lt;&amp;lt;
    /XObject &amp;lt;&amp;lt;/Im0 1 0 R&amp;gt;&amp;gt;
  &amp;gt;&amp;gt;
&amp;gt;&amp;gt;
endobj

12 0 obj
&amp;lt;&amp;lt;/Length 30&amp;gt;&amp;gt;
stream
q
  8 0 0 8 0 0 cm
  /Im0 Do
Q
endstream
endobj
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ensuite vient la table de références croisées ; elle indique l’&lt;em&gt;offset&lt;/em&gt; de
chacun des objets définis, dans l’ordre :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xref
0 13 
0000000000 65535 f 
0000000017 00000 n 
0000001861 00000 n 
0000001879 00000 n 
0000001897 00000 n 
0000001922 00000 n 
0000001945 00000 n 
0000001972 00000 n 
0000001999 00000 n 
0000002020 00000 n 
0000002076 00000 n 
0000002142 00000 n 
0000002309 00000 n 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;À chaque ajout ou suppression de caractères dans la définition des objets,
cette table doit être mise à jour.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Le fichier se termine par un &lt;em&gt;trailer&lt;/em&gt;, contenant l’&lt;em&gt;offset&lt;/em&gt; de la table de
références :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;trailer &amp;lt;&amp;lt; /Root 9 0 R /Size 13&amp;gt;&amp;gt;

startxref
2391
%%EOF
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ces &lt;em&gt;offsets&lt;/em&gt; sont un peu fastidieux à modifier à la main, mais ça fonctionne.&lt;/p&gt;

&lt;h2 id=&quot;shadow&quot;&gt;SHAdow&lt;/h2&gt;

&lt;p&gt;J’ai donc écrit un petit outil qui applique toutes ces opérations
automatiquement: &lt;a href=&quot;https://github.com/rom1v/shadow&quot;&gt;SHAdow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Il prend en entrée deux images JPEG (de moins de 64K, puisque la taille d’un
commentaire est codé sur 2 octets), ainsi que leurs dimensions (afin d’éviter
d’utiliser des dépendances pour les extraire) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./shadow.py img1.jpg img2.jpg 200 200
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Il génère deux fichiers dans le répertoire courant, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shadow1.pdf&lt;/code&gt; et
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shadow2.pdf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il ne reste qu’à vérifier qu’ils ont bien le même SHA-1 :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sha1sum shadow1.pdf shadow2.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
  
 
  
   
 <entry>
   <title>C++ sans *pointeurs</title>
   <link href="https://blog.rom1v.com/2017/01/cpp-sans-pointeurs/"/>
   <updated>2017-01-12T19:33:14+01:00</updated>
   <id>https://blog.rom1v.com/2017/01/cpp-sans-pointeurs</id>
   <content type="html">&lt;p&gt;Les &lt;a href=&quot;https://fr.wikipedia.org/wiki/Pointeur_%28programmation%29&quot;&gt;pointeurs&lt;/a&gt; sont utilisés plus souvent que nécessaire en &lt;a href=&quot;https://fr.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Je voudrais présenter ici comment caractériser les utilisations abusives et par
quoi les remplacer.&lt;/p&gt;

&lt;h2 id=&quot;objectifs&quot;&gt;Objectifs&lt;/h2&gt;

&lt;p&gt;La décision d’utiliser des pointeurs dépend en grande partie de l’&lt;a href=&quot;https://fr.wikipedia.org/wiki/Interface_de_programmation&quot;&gt;API&lt;/a&gt; des
objets utilisés.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;API est à comprendre dans un sens très large : je considère que des classes
utilisées dans une autre partie d’une même application exposent une API.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;L’objectif est donc de concevoir des API de manière à ce que leur utilisation ne
nécessite pas de manipuler de pointeurs, ni même si possible de &lt;em&gt;smart
pointers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Cela peut paraître surprenant, mais c’est en fait ainsi que vous utilisez les
classes de la &lt;a href=&quot;https://fr.wikipedia.org/wiki/Standard_Template_Library&quot;&gt;STL&lt;/a&gt; ou de &lt;a href=&quot;https://fr.wikipedia.org/wiki/Qt&quot;&gt;Qt&lt;/a&gt; : vos méthodes ne retournent jamais
un &lt;em&gt;raw pointer&lt;/em&gt; ni un &lt;em&gt;smart pointer&lt;/em&gt; vers une &lt;em&gt;string&lt;/em&gt; nouvellement créée.&lt;/p&gt;

&lt;p&gt;De manière générale, vous n’écririez pas ceci :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// STL version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Qt version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;ni ceci :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// STL version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;shared_ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make_shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Qt version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;À la place, vous écririez sûrement :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// STL version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;my name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Qt version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;my name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notre objectif est d’écrire des classes qui s’utiliseront de la même manière.&lt;/p&gt;

&lt;h2 id=&quot;ownership&quot;&gt;Ownership&lt;/h2&gt;

&lt;p&gt;Il faut distinguer deux types de &lt;em&gt;raw pointers&lt;/em&gt; :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ceux qui détiennent l’objet pointé (&lt;strong&gt;&lt;em&gt;owning&lt;/em&gt;&lt;/strong&gt;), qui devront être
libérés ;&lt;/li&gt;
  &lt;li&gt;ceux qui ne le détiennent pas (&lt;strong&gt;&lt;em&gt;non-owning&lt;/em&gt;&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Le plus simple est de les comparer sur un exemple.&lt;/p&gt;

&lt;h3 id=&quot;owning&quot;&gt;Owning&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* … */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// info must be deleted&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ici, nous avons la responsabilité de supprimer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;info&lt;/code&gt; au bon moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C’est ce type de pointeurs dont nous voulons nous débarrasser.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;non-owning&quot;&gt;Non-owning&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;writeDataTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QBuffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c++&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QBuffer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;writeDataTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ici, le pointeur permet juste de passer l’adresse de l’objet, mais la méthode
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writeDataTo(…)&lt;/code&gt; ne doit pas gérer sa durée de vie : elle ne le &lt;em&gt;détient&lt;/em&gt; donc
pas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cet usage est tout-à-fait légitime, nous souhaitons le conserver.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pour savoir si un pointeur est &lt;em&gt;owning&lt;/em&gt; ou non, il suffit de se poser la
question suivante : est-ce que lui affecter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nullptr&lt;/code&gt; provoquerait une &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_leak&quot;&gt;fuite
mémoire&lt;/a&gt; ?&lt;/p&gt;

&lt;h2 id=&quot;pourquoi&quot;&gt;Pourquoi ?&lt;/h2&gt;

&lt;p&gt;Voici quelques exemples illustrant pourquoi nous voulons éviter les &lt;em&gt;owning raw
pointers&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fuite-mémoire&quot;&gt;Fuite mémoire&lt;/h3&gt;

&lt;p&gt;Il est facile d’oublier de supprimer un pointeur dans des cas particuliers.&lt;/p&gt;

&lt;p&gt;Par exemple :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;createParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QFile&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QIODevice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ReadOnly&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// parser leaked if open failed&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ici, si l’ouverture du fichier a échoué, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parser&lt;/code&gt; ne sera jamais libéré.&lt;/p&gt;

&lt;p&gt;L’exemple suivant est encore plus significatif :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* … */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doWork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// result leaked&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Appeler une méthode sans s’occuper du résultat peut provoquer des fuites
mémoires.&lt;/p&gt;

&lt;h3 id=&quot;double-suppression&quot;&gt;Double suppression&lt;/h3&gt;

&lt;p&gt;Il est également possible, par inattention, de supprimer plusieurs fois le même
pointeur (ce qui entraîne un &lt;a href=&quot;/2014/10/comportement-indefini-et-optimisation/&quot;&gt;&lt;em&gt;undefined behavior&lt;/em&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Par exemple, si &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt; fait partie de la liste &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devices&lt;/code&gt;, ce code le supprime
deux fois :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;qDeleteAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// device is deleted twice&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;utilisation-après-suppression&quot;&gt;Utilisation après suppression&lt;/h3&gt;

&lt;p&gt;L’utilisation d’un pointeur après sa suppression est également indéfinie.&lt;/p&gt;

&lt;p&gt;Je vais prendre un exemple réel en Qt.&lt;/p&gt;

&lt;p&gt;Supposons qu’une classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeviceMonitor&lt;/code&gt; surveille le branchement de
périphériques, et crée pour chacun un objet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Device&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;suppression-complexe&quot;&gt;&lt;/a&gt;
Lorsqu’un périphérique est débranché, un &lt;a href=&quot;http://doc.qt.io/qt-5/signalsandslots.html&quot;&gt;signal Qt&lt;/a&gt; provoque
l’exécution du &lt;em&gt;slot&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeviceMonitor::onDeviceLeft(Device *)&lt;/code&gt;. Nous voulons
alors signaler au reste de l’application que le device est parti (&lt;em&gt;signal&lt;/em&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeviceMonitor::deviceLeft(Device *)&lt;/code&gt;), puis supprimer l’object &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt;
correspondant :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DeviceMonitor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onDeviceLeft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviceLeft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// slots may use the device after its deletion&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// device-&amp;gt;deleteLater() not sufficient&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais c’est loin d’être trivial.&lt;/p&gt;

&lt;p&gt;Si nous le supprimons immédiatement comme ceci, et qu’un &lt;em&gt;slot&lt;/em&gt; est branché à
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeviceMonitor::deviceLeft(Device *)&lt;/code&gt; en
&lt;a href=&quot;http://doc.qt.io/qt-5/qt.html#ConnectionType-enum&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qt::QueuedConnection&lt;/code&gt;&lt;/a&gt;, alors il est possible que le pointeur
soit déjà supprimé quand ce &lt;em&gt;slot&lt;/em&gt; sera exécuté.&lt;/p&gt;

&lt;p&gt;Un proverbe dit que quand ça crashe avec un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt;, &lt;em&gt;“il faut appeller
&lt;a href=&quot;http://doc.qt.io/qt-5/qobject.html#deleteLater&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deleteLater()&lt;/code&gt;&lt;/a&gt; pour corriger le problème”&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deleteLater&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais malheureusement, ici, c’est faux : si le &lt;em&gt;slot&lt;/em&gt; branché au &lt;em&gt;signal&lt;/em&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeviceMonitor::deviceLeft(Device *)&lt;/code&gt; est associé à un &lt;a href=&quot;http://doc.qt.io/qt-5/qobject.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QObject&lt;/code&gt;&lt;/a&gt;
vivant dans un autre &lt;a href=&quot;http://doc.qt.io/qt-5/qobject.html#thread-affinity&quot;&gt;thread&lt;/a&gt;, rien ne garantit que son
exécution aura lieu avant la suppression du pointeur.&lt;/p&gt;

&lt;p&gt;L’utilisation des &lt;em&gt;owning raw pointers&lt;/em&gt; n’est donc pas seulement vulnérable aux
erreurs d’inattention (comme dans les exemples précédents) : dans des cas plus
complexes, il devient &lt;strong&gt;difficile de déterminer quand supprimer le pointeur&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;responsabilité&quot;&gt;Responsabilité&lt;/h3&gt;

&lt;p&gt;De manière plus générale, lorsque nous avons un pointeur, nous ne savons pas
forcément qui a la responsabilité de le supprimer, ni comment le supprimer :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSomeData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ?&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ?&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;custom_deleter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ?&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Qt fournit un mécanisme pour supprimer automatiquement les &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QObject *&lt;/code&gt; quand
leur parent est détruit. Cependant, cette fonctionnalité ne s’applique qu’aux
&lt;a href=&quot;https://fr.wikipedia.org/wiki/Composition_%28programmation%29&quot;&gt;relations de composition&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Résumons les inconvénients des &lt;em&gt;owning raw pointeurs&lt;/em&gt; :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;la gestion mémoire est manuelle ;&lt;/li&gt;
  &lt;li&gt;leur utilisation est propice aux erreurs ;&lt;/li&gt;
  &lt;li&gt;la responsabilité de suppression n’est pas apparente ;&lt;/li&gt;
  &lt;li&gt;déterminer quand supprimer le pointeur peut être difficile.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;valeurs&quot;&gt;Valeurs&lt;/h2&gt;

&lt;p&gt;Laissons de côté les pointeurs quelques instants pour observer ce qu’il se passe
avec de simples &lt;em&gt;valeurs&lt;/em&gt; (des &lt;em&gt;objets&lt;/em&gt; plutôt que des &lt;em&gt;pointeurs vers des
objets&lt;/em&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finished&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;C’est plus simple : la gestion mémoire est automatique, et le code est plus sûr.
Par exemple, les fuites mémoire et les double suppressions sont impossibles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ce sont des avantages dont nous souhaiterions bénéficier également pour les
pointeurs.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;privilégier-les-valeurs&quot;&gt;Privilégier les valeurs&lt;/h3&gt;

&lt;p&gt;Dans les cas où les pointeurs sont utilisés uniquement pour éviter de retourner
des copies (et non pour partager des objets), il est préférable de &lt;strong&gt;retourner
les objets par valeur&lt;/strong&gt; à la place.&lt;/p&gt;

&lt;p&gt;Par exemple, si vous avez une classe :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Évitez :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Préférez :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Certes, dans certains cas, il est moins efficace de passer un objet par valeur
qu’à travers un pointeur (car il faut le copier).&lt;/p&gt;

&lt;p&gt;Mais cette inefficacité est à relativiser.&lt;/p&gt;

&lt;p&gt;D’abord parce que dans certains cas &lt;em&gt;(quand l’objet est copié à partir d’une
&lt;a href=&quot;http://thbecker.net/articles/rvalue_references/section_01.html&quot;&gt;rvalue reference&lt;/a&gt;)&lt;/em&gt;, la copie sera remplacée par un &lt;a href=&quot;http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html&quot;&gt;&lt;em&gt;move&lt;/em&gt;&lt;/a&gt;. Le &lt;em&gt;move&lt;/em&gt;
d’un &lt;a href=&quot;http://en.cppreference.com/w/cpp/container/vector&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vector&lt;/code&gt;&lt;/a&gt; par exemple n’entraîne aucune copie (ni &lt;em&gt;move&lt;/em&gt;) de ses
éléments.&lt;/p&gt;

&lt;p&gt;Ensuite parce que les compilateurs optimisent le retour par valeur
(&lt;a href=&quot;https://en.wikipedia.org/wiki/Return_value_optimization&quot;&gt;RVO&lt;/a&gt;), ce qui fait qu’en réalité dans les exemples ci-dessus, aucun &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt;
ni &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vector&lt;/code&gt; n’est jamais copié ni &lt;em&gt;mové&lt;/em&gt; : ils sont directement créés à
l’endroit où ils sont affectés &lt;em&gt;(sauf si vous compilez avec le paramètre
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-fno-elide-constructors&lt;/code&gt;)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Mais évidemment, il y a des cas où nous ne pouvons pas simplement remplacer un
&lt;em&gt;pointeur&lt;/em&gt; par une &lt;em&gt;valeur&lt;/em&gt;, par exemple quand un même objet doit être partagé
entre différentes parties d’un programme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nous voudrions les avantages des &lt;em&gt;valeurs&lt;/em&gt; également pour ces cas-là.&lt;/strong&gt; C’est
l’objectif de la suite du billet.&lt;/p&gt;

&lt;h2 id=&quot;idiomes-c&quot;&gt;Idiomes C++&lt;/h2&gt;

&lt;p&gt;Pour y parvenir, nous avons besoin de faire un détour par quelques &lt;em&gt;idiomes&lt;/em&gt;
couramment utilisés en C++.&lt;/p&gt;

&lt;p&gt;Ils ont souvent un nom étrange. Par exemple :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot;&gt;RAII&lt;/a&gt; &lt;em&gt;(Resource Acquisition Is Initialization)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Opaque_pointer&quot;&gt;PIMPL&lt;/a&gt; &lt;em&gt;(Pointer to IMPLementation)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern&quot;&gt;CRTP&lt;/a&gt; &lt;em&gt;(Curiously Recurring Template Pattern)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error&quot;&gt;SFINAE&lt;/a&gt; &lt;em&gt;(Substitution Failure Is Not An Error)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Immediately-invoked_function_expression&quot;&gt;IIFE&lt;/a&gt; &lt;em&gt;(Immediately-Invoked Function Expression)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous allons étudier les deux premiers.&lt;/p&gt;

&lt;h3 id=&quot;raii&quot;&gt;RAII&lt;/h3&gt;

&lt;p&gt;Prenons un exemple simple :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nous souhaitons rendre cette méthode &lt;a href=&quot;https://fr.wikipedia.org/wiki/Thread_safety&quot;&gt;thread-safe&lt;/a&gt; grâce à un &lt;a href=&quot;https://fr.wikipedia.org/wiki/Exclusion_mutuelle&quot;&gt;mutex&lt;/a&gt;
(&lt;a href=&quot;http://en.cppreference.com/w/cpp/thread/mutex&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::mutex&lt;/code&gt;&lt;/a&gt; en STL ou &lt;a href=&quot;http://doc.qt.io/qt-5/qmutex.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMutex&lt;/code&gt;&lt;/a&gt; en Qt).&lt;/p&gt;

&lt;p&gt;Supposons que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validate()&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;something()&lt;/code&gt; puissent lever une &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/exceptions&quot;&gt;exception&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Le &lt;em&gt;mutex&lt;/em&gt; doit être déverrouillé à la fin de l’exécution de la méthode. Le
problème, c’est que cela peut se produire à différents endroits, donc nous
devons gérer tous les cas :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(...)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le code est beaucoup plus complexe et propice aux erreurs.&lt;/p&gt;

&lt;p&gt;Avec des classes utilisant RAII (&lt;a href=&quot;http://en.cppreference.com/w/cpp/thread/lock_guard&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::lock_guard&lt;/code&gt;&lt;/a&gt; en STL ou
&lt;a href=&quot;http://doc.qt.io/qt-5/qmutexlocker.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMutexLocker&lt;/code&gt;&lt;/a&gt; en Qt), c’est beaucoup plus simple :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QMutexLocker&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;En ajoutant une seule ligne, la méthode est devenue &lt;em&gt;thread-safe&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Cette technique consiste à utiliser le cycle de vie d’un objet pour acquérir une
ressource dans le constructeur (ici verrouiller le &lt;em&gt;mutex&lt;/em&gt;) et la relâcher dans
le destructeur (ici le déverrouiller).&lt;/p&gt;

&lt;p&gt;Voici une implémentation simplifiée possible de &lt;a href=&quot;http://doc.qt.io/qt-5/qmutexlocker.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMutexLocker&lt;/code&gt;&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;QMutexLocker&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QMutex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;explicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QMutexLocker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMutex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMutexLocker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Comme l’objet est détruit lors de la sortie du &lt;em&gt;scope&lt;/em&gt; de la méthode (que ce
soit par un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; ou par une exception survenue n’importe où), le &lt;em&gt;mutex&lt;/em&gt;
sera &lt;strong&gt;toujours&lt;/strong&gt; déverrouillé.&lt;/p&gt;

&lt;p&gt;Au passage, dans l’exemple ci-dessus, nous remarquons que la variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;locker&lt;/code&gt;
n’est jamais utilisée. RAII complexifie donc la détection des &lt;em&gt;variables
inutilisées&lt;/em&gt;, car le compilateur doit détecter les effets de bords. Mais il s’en
sort bien : ici, il n’émet pas de &lt;em&gt;warning&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;smart-pointers&quot;&gt;Smart pointers&lt;/h2&gt;

&lt;p&gt;Les &lt;a href=&quot;https://en.wikipedia.org/wiki/Smart_pointer&quot;&gt;smart pointers&lt;/a&gt; utilisent RAII pour gérer automatiquement la durée de vie
des pointeurs. Il en existe plusieurs.&lt;/p&gt;

&lt;p&gt;Dans la STL :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/unique_ptr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::unique_ptr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/shared_ptr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/weak_ptr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::weak_ptr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/auto_ptr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::auto_ptr&lt;/code&gt;&lt;/a&gt; &lt;em&gt;(à bannir)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dans Qt :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qsharedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedPointer&lt;/code&gt;&lt;/a&gt; (équivalent de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qweakpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QWeakPointer&lt;/code&gt;&lt;/a&gt; (équivalent de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::weak_ptr&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qscopedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QScopedPointer&lt;/code&gt;&lt;/a&gt; (ersatz de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::unique_ptr&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qscopedarraypointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QScopedArrayPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qshareddatapointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedDataPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qexplicitlyshareddatapointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QExplicitlySharedDataPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;scoped-pointers&quot;&gt;Scoped pointers&lt;/h3&gt;

&lt;p&gt;Le &lt;em&gt;smart pointer&lt;/em&gt; le plus simple est le &lt;em&gt;scoped pointer&lt;/em&gt;. L’idée est vraiment
la même que &lt;a href=&quot;http://doc.qt.io/qt-5/qmutexlocker.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QMutexLocker&lt;/code&gt;&lt;/a&gt;, sauf qu’au lieu de vérouiller et
déverrouiller un &lt;em&gt;mutex&lt;/em&gt;, il stocke un &lt;em&gt;raw pointer&lt;/em&gt; et le supprime.&lt;/p&gt;

&lt;p&gt;En plus de cela, comme tous les &lt;em&gt;smart pointers&lt;/em&gt;, il &lt;a href=&quot;https://en.wikipedia.org/wiki/Operator_overloading&quot;&gt;redéfinit certains
opérateurs&lt;/a&gt; pour pouvoir être utilisé comme un &lt;em&gt;raw
pointer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Par exemple, voici une implémentation simplifiée possible de
&lt;a href=&quot;http://doc.qt.io/qt-5/qscopedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QScopedPointer&lt;/code&gt;&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;QScopedPointer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;explicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QScopedPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QScopedPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Q_DISABLE_COPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QScopedPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Et un exemple d’utilisation :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// bad design (owning raw pointer)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;DeviceInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getDeviceInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DeviceInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* … */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QScopedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DeviceInfo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getDeviceInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// used like a raw pointer&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;qDebug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;DeviceInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// automatically deleted&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;shared-pointers&quot;&gt;Shared pointers&lt;/h3&gt;

&lt;p&gt;Les &lt;em&gt;shared pointers&lt;/em&gt; permettent de partager l’&lt;em&gt;ownership&lt;/em&gt; (la responsabilité de
suppression) d’une ressource.&lt;/p&gt;

&lt;p&gt;Ils contiennent un &lt;a href=&quot;https://en.wikipedia.org/wiki/Reference_counting&quot;&gt;compteur de références&lt;/a&gt;, indiquant le nombre
d’instances partageant le même pointeur. Lorsque ce compteur tombe à 0, le
pointeur est supprimé (il faut donc éviter les &lt;a href=&quot;https://en.wikipedia.org/wiki/Reference_counting#Dealing_with_reference_cycles&quot;&gt;cycles&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;En pratique, voici ce à quoi ressemblerait une liste de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Device&lt;/code&gt;s &lt;em&gt;partagés&lt;/em&gt; par
des &lt;a href=&quot;http://doc.qt.io/qt-5/qsharedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedPointer&lt;/code&gt;&lt;/a&gt;s :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DeviceList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getDevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// devices are automatically deleted when necessary&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le &lt;em&gt;partage&lt;/em&gt; d’un pointeur découle toujours de la copie d’un &lt;em&gt;shared pointer&lt;/em&gt;.
C’est la raison pour laquelle &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getDevice(…)&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add(…)&lt;/code&gt; manipulent un
&lt;a href=&quot;http://doc.qt.io/qt-5/qsharedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedPointer&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Le piège à éviter est de créér plusieurs &lt;em&gt;smart pointers&lt;/em&gt; indépendants sur le
même &lt;em&gt;raw pointer&lt;/em&gt;. Dans ce cas, il y aurait deux &lt;em&gt;refcounts&lt;/em&gt; à 1 plutôt qu’un
&lt;em&gt;refcount&lt;/em&gt; à 2, et le pointeur serait supprimé dès la destruction du premier
&lt;em&gt;shared pointer&lt;/em&gt;, laissant l’autre &lt;a href=&quot;https://fr.wikipedia.org/wiki/Dangling_pointer&quot;&gt;&lt;em&gt;pendouillant&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Petite parenthèse : la signature des méthodes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remove&lt;/code&gt; sont
différentes car une suppression ne nécessite pas de &lt;a href=&quot;https://www.youtube.com/watch?v=xnqTKD8uD64&amp;amp;t=18m38s&quot;&gt;manipuler la durée de
vie&lt;/a&gt; du &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Device&lt;/code&gt; passé en paramètre.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Refcounted smart pointers are about managing te owned object’s lifetime.&lt;/p&gt;

  &lt;p&gt;Copy/assign one only when you intend to manipulate the owned object’s
lifetime.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Au passage, si en Qt vous passez vos objets de la couche C++ à la couche
&lt;a href=&quot;https://en.wikipedia.org/wiki/QML&quot;&gt;QML&lt;/a&gt;, il faut aussi passer les &lt;em&gt;shared pointers&lt;/em&gt; afin de ne pas casser le
partage, ce qui implique d’enregistrer le type :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;registerQml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;qRegisterMetaType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Listons donc les avantages des &lt;em&gt;shared pointers&lt;/em&gt; :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;la gestion mémoire est automatique ;&lt;/li&gt;
  &lt;li&gt;l’&lt;em&gt;ownership&lt;/em&gt; est géré automatiquement ;&lt;/li&gt;
  &lt;li&gt;l’utilisation est moins propice aux erreurs (à part la possibilité de créer
des &lt;em&gt;smart pointers&lt;/em&gt; indépendants sur le même &lt;em&gt;raw pointer&lt;/em&gt;) ;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cependant, si la gestion mémoire est &lt;strong&gt;automatique&lt;/strong&gt;, elle n’est pas
&lt;strong&gt;transparente&lt;/strong&gt; : elle nécessite de manipuler explicitement des
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedPointer&lt;/code&gt;, ce qui est verbeux.&lt;/p&gt;

&lt;p&gt;Il est certes possible d’utiliser un &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/type_alias&quot;&gt;alias&lt;/a&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Typedef&quot;&gt;typedef&lt;/a&gt;) pour atténuer la
verbosité :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DevicePtr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DeviceList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DevicePtr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;DevicePtr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getDevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DevicePtr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais quoi qu’il en soit, &lt;strong&gt;cela reste plus complexe que des &lt;em&gt;valeurs&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pour aller plus loin, nous allons devoir faire un détour inattendu, par un
&lt;em&gt;idiome&lt;/em&gt; qui n’a a priori rien à voir.&lt;/p&gt;

&lt;h2 id=&quot;pimpl&quot;&gt;PImpl&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Opaque_pointer&quot;&gt;PImpl&lt;/a&gt; sert à réduire les dépendances de compilation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Opaque pointers are a way to hide the implementation details of an interface
from ordinary clients, so that the implementation may be changed without the
need to recompile the modules using it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Prenons la classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; suivante (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.h&lt;/code&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countYears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Elle contient juste un &lt;em&gt;nom&lt;/em&gt; et un &lt;em&gt;âge&lt;/em&gt;. Elle définit par ailleurs une méthode
privée, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;countYears(…)&lt;/code&gt;, qu’on imagine appelée dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAge()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Chaque classe désirant utiliser la classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; devra l’inclure :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;person.h&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Par conséquent, à chaque modification de ces parties privées (qui sont pourtant
que des détails d’implémentation), &lt;strong&gt;toutes les classes incluant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.h&lt;/code&gt;
devront être recompilées&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;C’est ce que &lt;em&gt;PImpl&lt;/em&gt; permet d’éviter, en séparant la classe en deux :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;une interface publique ;&lt;/li&gt;
  &lt;li&gt;une implémentation privée.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Concrètement, la classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; précédente est la partie privée. Renommons-la :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonPrivate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countYears&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Créons la partie publique, définissant l’interface souhaitée :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// forward declaration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PersonPrivate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Elle contient un pointeur vers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersonPrivate&lt;/code&gt;, et lui délègue tous les appels.&lt;/p&gt;

&lt;p&gt;Évidemment, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; ne doit pas inclure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersonPrivate&lt;/code&gt;, sinon nous aurions les
mêmes dépendances de compilation, et nous n’aurions rien résolu. Il faut
utiliser à la place une &lt;a href=&quot;https://en.wikipedia.org/wiki/Forward_declaration&quot;&gt;&lt;em&gt;forward declaration&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Voici son implémentation :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le pointeur vers la classe privée est souvent nommé &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; car il s’agit d’un
&lt;a href=&quot;https://wiki.qt.io/D-Pointer&quot;&gt;d-pointer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Donc comme prévu, tout cela n’a rien à voir avec notre objectif d’éviter
d’utiliser des pointeurs.&lt;/p&gt;

&lt;h2 id=&quot;partage&quot;&gt;Partage&lt;/h2&gt;

&lt;p&gt;Mais en fait, si. &lt;em&gt;PImpl&lt;/em&gt; permet de séparer les classes manipulées explicitement
de l’objet réellement modifié :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/nopointers/pimpl.png&quot; alt=&quot;graph_pimpl&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Il y a une relation 1-1 entre la classe publique et la classe privée
correspondante. Mais nous pouvons imaginer d’autres &lt;a href=&quot;https://fr.wikipedia.org/wiki/Cardinalit%C3%A9_%28programmation%29&quot;&gt;cardinalités&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Par exemple, Qt &lt;a href=&quot;http://doc.qt.io/qt-5/implicit-sharing.html&quot;&gt;partage implicitement&lt;/a&gt; les parties privées
d’un grand nombre de &lt;a href=&quot;http://doc.qt.io/qt-5/implicit-sharing.html#list-of-classes&quot;&gt;classes&lt;/a&gt;. Il ne les copie que
lors d’une écriture (&lt;a href=&quot;https://fr.wikipedia.org/wiki/Copy-on-write&quot;&gt;CoW&lt;/a&gt;) :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/nopointers/pimpl_shareddata.png&quot; alt=&quot;graph_pimpl_shareddata&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Par exemple, lorsqu’une &lt;a href=&quot;http://doc.qt.io/qt-5/qstring.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QString&lt;/code&gt;&lt;/a&gt; est copiée, la même zone mémoire
sera utilisée pour les différentes instances, jusqu’à ce qu’une modification
survienne.&lt;/p&gt;

&lt;p&gt;Cependant, il ne s’agit que d’un détail d’implémentation utilisé pour améliorer
les performances. Du point de vue utilisateur, tout se passe comme si les
données étaient réellement copiées :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ABC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Q_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ABCDEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Q_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ABC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;En d’autres termes, &lt;strong&gt;les classes publiques ci-dessus ont une &lt;a href=&quot;https://en.wikipedia.org/wiki/Value_semantics&quot;&gt;sémantique de
valeur&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;resource-handles&quot;&gt;Resource handles&lt;/h3&gt;

&lt;p&gt;À la place, nous pouvons décider de partager inconditionnellement la partie
privée, y compris après une écriture :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/nopointers/pimpl_shared.png&quot; alt=&quot;graph_pimpl_shared&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Dans ce cas, &lt;strong&gt;la classe publique a sémantique d’entité&lt;/strong&gt;. Elle est qualifiée de
&lt;em&gt;resource handle&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;C’est bien sûr le cas des &lt;em&gt;smart pointers&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ABC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Q_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Q_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais aussi d’autres classes, comme l’&lt;a href=&quot;http://doc.qt.io/qt-5/qdomdocument.html#details&quot;&gt;API Dom de Qt&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QDomDocument&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QDomElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QDomElement&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;documentElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insertAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{});&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// the document is modified&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;pimpl-avec-des-smart-pointers&quot;&gt;PImpl avec des &lt;em&gt;smart pointers&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Tout-à-l’heure, j’ai présenté &lt;em&gt;PImpl&lt;/em&gt; en utilisant un &lt;em&gt;owning raw pointer&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// forward declaration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// this is a raw pointer!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PersonPrivate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais en fait, à chaque type de relation correspond un type de &lt;em&gt;smart pointer&lt;/em&gt;
directement utilisable pour &lt;em&gt;PImpl&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Pour une relation 1-1 classique :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/unique_ptr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::unique_ptr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qscopedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QScopedPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour une relation 1-N à sémantique de valeur (CoW) :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qshareddatapointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedDataPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour une relation 1-N à sémantique d’entité :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.cppreference.com/w/cpp/memory/shared_ptr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://doc.qt.io/qt-5/qsharedpointer.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QSharedPointer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Par exemple, donnons à notre classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; une sémantique d’entité :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// forward declaration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QSharedPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PersonPrivate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// a &quot;null&quot; person&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// shared handles should expose const methods&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; se comporte maintenant &lt;em&gt;comme un pointeur&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ABC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Q_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Q_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DEF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p1&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p2&lt;/code&gt; sont alors des &lt;em&gt;resource handles&lt;/em&gt; vers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersonPrivate&lt;/code&gt; :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/nopointers/shared_person.png&quot; alt=&quot;graph_shared_person&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Évidemment, ce n’est pas approprié pour la classe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt;, car le comportement
est trop inattendu.&lt;/p&gt;

&lt;p&gt;Mais je vais présenter un cas réel où ce &lt;em&gt;design&lt;/em&gt; est approprié.&lt;/p&gt;

&lt;h2 id=&quot;en-pratique&quot;&gt;En pratique&lt;/h2&gt;

&lt;p&gt;&lt;a id=&quot;libusb-wrappers&quot;&gt;&lt;/a&gt;
Pour l’entreprise dans laquelle je suis salarié, j’ai implémenté une
fonctionnalité permettant d’utiliser une souris USB branchée sur un PC pour
contrôler un téléphone Android connecté en USB.&lt;/p&gt;

&lt;p&gt;Concrètement, cela consiste à tranférer (grâce à &lt;a href=&quot;http://libusb.info&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb&lt;/code&gt;&lt;/a&gt;), à partir
du PC, les événements &lt;a href=&quot;https://en.wikipedia.org/wiki/Human_interface_device&quot;&gt;HID&lt;/a&gt; reçus de la souris vers le téléphone Android.&lt;/p&gt;

&lt;p&gt;J’ai donc (entre autres) créé des &lt;em&gt;resources handles&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDevice&lt;/code&gt; et
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDeviceHandle&lt;/code&gt; qui wrappent les structures C &lt;a href=&quot;http://libusb.sourceforge.net/api-1.0/group__dev.html#ga77eedd00d01eb7569b880e861a971c2b&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb_device&lt;/code&gt;&lt;/a&gt;
et &lt;a href=&quot;http://libusb.sourceforge.net/api-1.0/group__dev.html#ga7df95821d20d27b5597f1d783749d6a4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb_device_handle&lt;/code&gt;&lt;/a&gt;, suivant les principes
détaillés dans ce billet.&lt;/p&gt;

&lt;p&gt;Leur utilisation illustre bien, d’après moi, les bénéfices d’une telle
conception.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UsbDeviceMonitor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAnyDroid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAnyMouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;signals:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviceArrived&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviceLeft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDevice&lt;/code&gt; peut être retourné par valeur, et passé en paramètre d’un &lt;em&gt;signal&lt;/em&gt;
par &lt;em&gt;const reference&lt;/em&gt; (exactement comme nous le ferions avec un
&lt;a href=&quot;http://doc.qt.io/qt-5/qstring.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QString&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDeviceMonitor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getAnyMouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isMouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Si une souris est trouvée dans la liste, on la retourne simplement ; sinon, on
retourne un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDevice&lt;/code&gt; “&lt;a href=&quot;http://doc.qt.io/qt-5/qstring.html#isNull&quot;&gt;&lt;em&gt;null&lt;/em&gt;&lt;/a&gt;”.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDeviceMonitor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onHotplugDeviceArrived&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviceArrived&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;La gestion mémoire est totalement automatique et transparente. Les &lt;a href=&quot;#suppression-complexe&quot;&gt;problèmes
présentés&lt;/a&gt; sont résolus.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;registerQml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;qRegisterMetaType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// QML&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;startForwarding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;usbDeviceMonitor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAnyMouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;droid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;usbDeviceMonitor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAnyDroid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;worker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;droid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDevice&lt;/code&gt; peut naviguer entre la couche C++ et QML.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsbDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;droid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UsbDeviceHandle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;droidHandle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;droid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;droidHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UsbDeviceHandle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouseHandle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mouseHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Grâce à RAII, les connexions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDeviceHandle&lt;/code&gt;) sont fermées automatiquement.&lt;/p&gt;

&lt;p&gt;En particulier, si la connexion à la souris échoue, la connexion au téléphone
Android est automatiquement fermée.&lt;/p&gt;

&lt;h2 id=&quot;résultat&quot;&gt;Résultat&lt;/h2&gt;

&lt;p&gt;Dans ces différents exemples, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt; ne sont jamais utilisés, et
&lt;strong&gt;par construction, la mémoire sera correctement gérée&lt;/strong&gt;. Ou plus précisément,
si un problème de gestion mémoire existe, il se situera dans l’implémentation de
la classe elle-même, et non partout où elle est utilisée.&lt;/p&gt;

&lt;p&gt;Ainsi, nous manipulons des &lt;em&gt;handles&lt;/em&gt; se comportant comme des &lt;em&gt;pointeurs&lt;/em&gt;, ayant
les mêmes avantages que les &lt;em&gt;valeurs&lt;/em&gt; :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;gestion mémoire &lt;strong&gt;automatique&lt;/strong&gt; et &lt;strong&gt;transparente&lt;/strong&gt; ;&lt;/li&gt;
  &lt;li&gt;simple ;&lt;/li&gt;
  &lt;li&gt;efficace ;&lt;/li&gt;
  &lt;li&gt;sûr et robuste.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ils peuvent par contre présenter quelques limitations.&lt;/p&gt;

&lt;p&gt;Par exemple, ils sont incompatibles avec &lt;a href=&quot;http://doc.qt.io/qt-5/qobject.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QObject&lt;/code&gt;&lt;/a&gt;. En effet,
techniquement, la classe d’un &lt;em&gt;resource handle&lt;/em&gt; doit pouvoir être copiée (pour
supporter le passage par &lt;em&gt;valeur&lt;/em&gt;), alors qu’un &lt;a href=&quot;http://doc.qt.io/qt-5/qobject.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QObject&lt;/code&gt;&lt;/a&gt; &lt;a href=&quot;http://doc.qt.io/qt-5/object.html#identity-vs-value&quot;&gt;n’est pas
copiable&lt;/a&gt; :&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QObject&lt;/code&gt;s are &lt;em&gt;identities&lt;/em&gt;, not &lt;em&gt;values&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Très concrètement, cela implique que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbDevice&lt;/code&gt; ne pourrait pas supporter de
&lt;em&gt;signaux&lt;/em&gt; (en tout cas, pas directement). C’est d’ailleurs le cas de beaucoup de
classes de Qt : par exemple &lt;a href=&quot;http://doc.qt.io/qt-5/qstring.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QString&lt;/code&gt;&lt;/a&gt; et &lt;a href=&quot;http://doc.qt.io/qt-5/qlist.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QList&lt;/code&gt;&lt;/a&gt; n’héritent
pas de &lt;a href=&quot;http://doc.qt.io/qt-5/qobject.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QObject&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;résumé&quot;&gt;Résumé&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decide&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;semantics&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mustAvoidCopies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;just use values&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;use PImpl + QSharedDataPointer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// semantics == ENTITY&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entitySemanticsIsObvious&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;use PImpl + QSharedPointer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;use smart pointers explicitly&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;C’est juste une heuristique…&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;En suivant ces principes, nous pouvons nous débarrasser des &lt;em&gt;owning
raw pointers&lt;/em&gt; et des &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt; “nus”. Cela contribue à rendre le code
plus simple et plus robuste.&lt;/p&gt;

&lt;p&gt;Ce sont d’ailleurs des objectifs qui guident les évolutions du langage C++ :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.stroustrup.com/resource-model.pdf&quot;&gt;A brief introduction to C++’s model for type and resource-safety&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/isocpp/CppCoreGuidelines/blob/master/talks/Stroustrup%20-%20CppCon%202015%20keynote.pdf&quot;&gt;Writing good C++14&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://herbsutter.com/elements-of-modern-c-style/&quot;&gt;Elements of Modern C++ Style&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return 0;&lt;/code&gt;&lt;/p&gt;
</content>
 </entry>
  
 
  
   
 <entry>
   <title>Commentaires statiques avec Jekyll</title>
   <link href="https://blog.rom1v.com/2017/01/commentaires-statiques-avec-jekyll/"/>
   <updated>2017-01-09T18:06:04+01:00</updated>
   <id>https://blog.rom1v.com/2017/01/commentaires-statiques-avec-jekyll</id>
   <content type="html">&lt;p&gt;Pour ce blog, j’ai abandonné
&lt;a href=&quot;https://fr.wikipedia.org/wiki/WordPres://fr.wordpress.org/&quot;&gt;Wordpress&lt;/a&gt; pour
&lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, un moteur de blog &lt;em&gt;statique&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ainsi, j’écris mes articles en &lt;a href=&quot;https://fr.wikipedia.org/wiki/Markdown&quot;&gt;markdown&lt;/a&gt; dans mon &lt;a href=&quot;https://fr.wikipedia.org/wiki/Vim&quot;&gt;éditeur favori&lt;/a&gt;, je
les &lt;em&gt;commite&lt;/em&gt; dans un &lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/&quot;&gt;dépôt git&lt;/a&gt;, et je génère le blog avec :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jekyll build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Le contenu hébergé étant statique, les pages ainsi générées à partir des sources
sont renvoyées telles quelles.&lt;/p&gt;

&lt;p&gt;Ce fonctionnement a beaucoup d’avantages :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;le temps de réponse est minimal ;&lt;/li&gt;
  &lt;li&gt;la sécurité est largement accrue ;&lt;/li&gt;
  &lt;li&gt;la maintenance est simplifiée (pas de mises à jour de sécurité régulières) ;&lt;/li&gt;
  &lt;li&gt;le backup est trivial (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone&lt;/code&gt;, pas de base de données).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;sans-commentaires&quot;&gt;Sans commentaires&lt;/h2&gt;

&lt;p&gt;L’inconvénient, c’est qu’un contenu statique est difficilement conciliable avec
le support des commentaires (il faut bien d’une manière ou d’une autre exécuter
du code lors de la réception d’un commentaire).&lt;/p&gt;

&lt;p&gt;Il y a plusieurs manières de contourner le problème.&lt;/p&gt;

&lt;p&gt;Il est par exemple possible d’en déporter la gestion (sur un service en ligne
comme &lt;a href=&quot;http://www.perfectlyrandom.org/2014/06/29/adding-disqus-to-your-jekyll-powered-github-pages/&quot;&gt;Disqus&lt;/a&gt; ou un équivalent libre – &lt;a href=&quot;https://posativ.org/isso/&quot;&gt;isso&lt;/a&gt; – à héberger
soi-même). Ainsi, les commentaires peuvent être chargés séparément par le client
en &lt;em&gt;Javascript&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Au lieu de cela, j’ai choisi d’intégrer les commentaires aux sources du blog.
Voici comment.&lt;/p&gt;

&lt;p&gt;L’objectif est d’une part de pouvoir &lt;strong&gt;stocker&lt;/strong&gt; et &lt;strong&gt;afficher&lt;/strong&gt; les commentaires
existants, et d’autre part de fournir aux lecteurs la possibilité d’en
&lt;strong&gt;soumettre&lt;/strong&gt; de nouveaux, qui me seront &lt;strong&gt;envoyés par e-mail&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Je me suis principalement inspiré du contenu de &lt;a href=&quot;http://theshed.hezmatt.org/jekyll-static-comments/&quot;&gt;Jekyll::StaticComments&lt;/a&gt;, même
si, comme nous allons le voir, je n’utilise pas le plug-in lui-même.&lt;/p&gt;

&lt;h2 id=&quot;stockage&quot;&gt;Stockage&lt;/h2&gt;

&lt;p&gt;L’idée est de stocker les commentaires quelque part dans les sources du site au
format &lt;a href=&quot;https://fr.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Le plugin &lt;em&gt;Jekyll::StaticComments&lt;/em&gt; nécessite de stocker &lt;a href=&quot;https://github.com/mpalmer/jekyll-static-comments/blob/master/README.md#technical-details&quot;&gt;un fichier par
commentaire&lt;/a&gt; dans un dossier spécial (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_comments&lt;/code&gt;) parsé par un
script à insérer dans le répertoire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_plugins&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Personnellement, je préfère avoir tous les commentaires d’un même post regroupés
au sein d’un même fichier. Et pour cela, pas besoin de plug-in : nous pouvons
faire &lt;a href=&quot;http://stevesspace.com/2014/04/static-jekyll-comments/&quot;&gt;correspondre&lt;/a&gt; à chaque post dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; une liste de
commentaires dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_data&lt;/code&gt; (un répertoire géré nativement par &lt;em&gt;Jekyll&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Par exemple, ce billet est stocké dans :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;_posts/2017-01-09-commentaires-statiques-avec-jekyll.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dans l’idéal, je voudrais que les commentaires associés soient stockés dans :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;_data/comments-2017-01-09-commentaires-statiques-avec-jekyll.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;En pratique, pour des raisons techniques (&lt;a href=&quot;https://github.com/jekyll/jekyll/issues/633&quot;&gt;&lt;em&gt;Jekyll&lt;/em&gt; ne donne pas accès au nom du
fichier&lt;/a&gt;), le nom du fichier ne contient pas le numéro du jour :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;_data/comments-2017-01-commentaires-statiques-avec-jekyll.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Il suffit alors de stocker dans ces fichiers les commentaires sous cette forme :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;this_is_me&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2017-01-02 10:11:12+01:00&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;Bonjour,&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;Ceci est un commentaire écrit en _markdown_.&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;dev42&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;author-url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2017-01-02 12:11:10+01:00&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;gt; Ceci est un commentaire écrit en _markdown_.&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;Et ça supporte aussi le [Liquid](https://jekyllrb.com/docs/templates/) :&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;{% highlight c %}&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;int main() {&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;return 0;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;{% endhighlight %}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour des exemples réels, voir les &lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/tree/master/_data&quot;&gt;sources des commentaires&lt;/a&gt; de ce
blog.&lt;/p&gt;

&lt;h2 id=&quot;affichage&quot;&gt;Affichage&lt;/h2&gt;

&lt;p&gt;Maintenant que nous avons les données des commentaires, nous devons les
afficher.&lt;/p&gt;

&lt;p&gt;Il faut d’abord trouver la liste des commentaires associée à la page courante.&lt;/p&gt;

&lt;p&gt;Comme nous ne pouvons pas récupérer directement le nom du fichier d’une page,
nous devons reconstruire la chaîne à partir de la &lt;a href=&quot;https://jekyllrb.com/docs/variables/#page-variables&quot;&gt;variable&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;page.id&lt;/code&gt;, qui
ici vaut :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/2017/01/commentaires-statiques-avec-jekyll
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Cette ligne de &lt;em&gt;Liquid&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-liquid&quot; data-lang=&quot;liquid&quot;&gt;comments&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;-&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;donne la valeur :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;comments-2017-01-commentaires-statiques-avec-jekyll
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nous avons donc tout ce dont nous avons besoin pour créer le &lt;em&gt;template&lt;/em&gt; de
commentaires (à stocker dans &lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/blob/master/_includes/comments.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/comments.html&lt;/code&gt;&lt;/a&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;{% capture commentid %}comments{{ page.id | replace: &apos;/&apos;, &apos;-&apos; }}{% endcapture %}
{% if site.data[commentid] %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comments&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Commentaires&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comments&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    {% for comment in site.data[commentid] %}
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-{{ comment.id }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-author&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {% if (comment.author-url) %}
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{comment.author-url}}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {% endif %}
                {{ comment.author }}
                {% if (comment.author-url) %}
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                {% endif %}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-date&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#comment-{{ comment.id }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    {{ comment.date | date: &quot;%-d %B %Y, %H:%M&quot; }}
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-contents&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                {{ comment.contents | liquify | markdownify }}
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    {% endfor %}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Il suffit alors d’inclure cette page à l’endroit où vous souhaitez insérer les
commentaires (typiquement dans &lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/blob/master/_layouts/post.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layout/post.html&lt;/code&gt;&lt;/a&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-liquid&quot; data-lang=&quot;liquid&quot;&gt;&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;comments.html&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;formulaire&quot;&gt;Formulaire&lt;/h2&gt;

&lt;p&gt;Pour proposer aux utilisateurs de poster de nouveaux commentaires, il nous faut
un formulaire.&lt;/p&gt;

&lt;p&gt;À titre d’exemple, voici le mien (intégré à
&lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/blob/master/_includes/comments.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/comments.html&lt;/code&gt;&lt;/a&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;h3&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-title&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Poster un commentaire&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;method=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POST&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/comments/submit.php&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post_id&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.id }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;return_url&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ page.url }}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;table&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-table&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Nom :&lt;span class=&quot;nt&quot;&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;size=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;25&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;em&amp;gt;&lt;/span&gt;(requis)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/em&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;th&amp;gt;&lt;/span&gt;E-mail :&lt;span class=&quot;nt&quot;&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;size=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;25&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;email&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;em&amp;gt;&lt;/span&gt;(requis, non publié)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/em&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Site web :&lt;span class=&quot;nt&quot;&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;size=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;25&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;url&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;em&amp;gt;&lt;/span&gt;(optionnel)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/em&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;colspan=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rows=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;colspan=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;comment-submit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Envoyer&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ce formulaire est affiché sous les commentaires existants.&lt;/p&gt;

&lt;h2 id=&quot;traitement&quot;&gt;Traitement&lt;/h2&gt;

&lt;p&gt;L’&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;action&lt;/code&gt; du formulaire précédent pointait sur
&lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/blob/master/comments/submit.php&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;comments/submit.php&lt;/code&gt;&lt;/a&gt;. Il nous reste donc à écrire dans ce fichier
le code à exécuter lorsqu’un utilisateur envoie un commentaire au serveur.&lt;/p&gt;

&lt;p&gt;Ce sera la seule partie “dynamique” du site.&lt;/p&gt;

&lt;p&gt;Voici les parties importantes de &lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/blob/master/comments/submit.php&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;comments/submit.php&lt;/code&gt;&lt;/a&gt; (basé sur
&lt;a href=&quot;https://github.com/mpalmer/jekyll-static-comments/blob/master/commentsubmit.php&quot;&gt;la version de Jekyll::StaticComments&lt;/a&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$DATE_FORMAT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Y-m-d H:i:sP&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$EMAIL_ADDRESS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;your@email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$SUBJECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Nouveau commentaire&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$COMMENT_SENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sent.html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;post_id: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;post_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;email: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;---&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;- id: ?&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;  author: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;  author-url: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;  date: &quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DATE_FORMAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;  contents: |&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_POST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;comment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;From: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$EMAIL_ADDRESS&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: text/plain; charset=utf-8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$EMAIL_ADDRESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SUBJECT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$COMMENT_SENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Le commentaire n&apos;a pas pu être envoyé.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Quand un commentaire est envoyé avec succès, la page
&lt;a href=&quot;https://github.com/rom1v/blog.rom1v.com/blob/master/comments/sent.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;comments/sent.html&lt;/code&gt;&lt;/a&gt; est affichée à l’utilisateur.&lt;/p&gt;

&lt;p&gt;Ainsi, lorsqu’un commentaire est posté, je reçois un mail :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;post_id: /2017/01/commentaires-statiques-avec-jekyll
email: my@email
---
- id: ?
  author: ®om
  author-url: http://blog.rom1v.com
  date: 2017-01-09 19:27:10+01:00
  contents: |
Ceci est un test.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;J’ai d’ailleurs ajouté une règle &lt;a href=&quot;/2010/01/trier-ses-mails-directement-sur-le-serveur-procmail/&quot;&gt;procmail&lt;/a&gt; pour que ces mails arrivent dans
un dossier dédié.&lt;/p&gt;

&lt;p&gt;Je peux alors copier le contenu dans le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.yaml&lt;/code&gt; correspondant, formatter le
commentaire (entre autres l’indenter de 4 espaces, ce qu’on pourrait
automatiser), et le commiter.&lt;/p&gt;

&lt;h2 id=&quot;résumé&quot;&gt;Résumé&lt;/h2&gt;

&lt;p&gt;Une fois mis en place, vous devriez donc avoir les fichiers suivants :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_data/comments-*.yaml&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/comments.html&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;comments/submit.php&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;comments/sent.html&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Je souhaitais depuis longtemps migrer vers un moteur de blog statique, qui
correspond davantage à ma façon d’écrire des articles, et offre beaucoup
d’avantages (légèreté, sécurité, maintenance…).&lt;/p&gt;

&lt;p&gt;Je suis très content d’y être parvenu sans perdre les commentaires ni la
possibilité d’en poster de nouveaux.&lt;/p&gt;

&lt;p&gt;Certes, la validation est très manuelle, mais c’est le prix à payer pour avoir
des commentaires statiques. Pour un blog avec une fréquence de commentaires
assez faible, je pense que ce n’est pas très gênant.&lt;/p&gt;
</content>
 </entry>
  
 
  
 
  
 
  
   
 <entry>
   <title>Comportement indéfini et optimisation</title>
   <link href="https://blog.rom1v.com/2014/10/comportement-indefini-et-optimisation/"/>
   <updated>2014-10-22T00:41:59+02:00</updated>
   <id>https://blog.rom1v.com/2014/10/comportement-indefini-et-optimisation</id>
   <content type="html">&lt;p&gt;Dans certains langages (typiquement &lt;a href=&quot;https://fr.wikipedia.org/wiki/C_%28langage%29&quot;&gt;C&lt;/a&gt; et &lt;a href=&quot;https://fr.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;), la sémantique de
certaines opérations est &lt;a href=&quot;https://en.wikipedia.org/wiki/Undefined_behavior&quot;&gt;&lt;em&gt;indéfinie&lt;/em&gt;&lt;/a&gt;. Cela permet au
compilateur de ne s’intéresser qu’aux cas qui sont définis (et donc de les
optimiser) sans s’occuper des effets produits sur les cas indéfinis.&lt;/p&gt;

&lt;p&gt;C’est un concept très précieux pour améliorer sensiblement les performances.
Mais cela peut avoir des effets surprenants. Si le résultat de votre programme
dépend d’un &lt;em&gt;comportement indéfini&lt;/em&gt; (undefined behavior) particulier, alors
votre programme complet n’a pas de sens, et le compilateur a le droit de faire
ce qu’il veut. Et il ne s’en prive pas !&lt;/p&gt;

&lt;h2 id=&quot;programme-indéfini&quot;&gt;Programme indéfini&lt;/h2&gt;

&lt;p&gt;Par exemple, &lt;a href=&quot;https://en.wikipedia.org/wiki/Pointer_%28computer_programming%29#cite_ref-7&quot;&gt;déréférencer un pointeur NULL&lt;/a&gt; est un
&lt;em&gt;comportement indéfini&lt;/em&gt;. En effet, contrairement à ce que beaucoup pensent,
l’exécution du programme ne va pas forcément provoquer une &lt;a href=&quot;https://fr.wikipedia.org/wiki/Erreur_de_segmentation&quot;&gt;erreur de
segmentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;J’ai écrit un petit programme tout simple (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined.c&lt;/code&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;malloc.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pwnd %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Si &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argc&lt;/code&gt; vaut &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; (c’est-à-dire si nous appelons l’exécutable sans passer
d’arguments de la ligne de commande), alors le pointeur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; est &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; (ligne
5).&lt;/p&gt;

&lt;p&gt;Cette ligne peut paraître étrange, mais elle permet de faire dépendre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; d’une
valeur connue uniquement à l’exécution (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argc&lt;/code&gt;), ce qui évite au compilateur de
savoir à l’avance que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; est &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La ligne 6 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*i = 42&lt;/code&gt;) est donc incorrecte : nous n’avons pas le droit de
déréférencer un pointeur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;. Nous nous attendons donc souvent à une erreur
de segmentation.&lt;/p&gt;

&lt;p&gt;Mais suite à ce que je viens de vous dire, admettons que ce ne soit pas le cas,
et que nous arrivions quand même sur la ligne suivante (7). Ici, si &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; est
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;, la fonction se termine (en retournant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, ligne 8).&lt;/p&gt;

&lt;p&gt;Donc il n’y a donc aucun moyen d’afficher le contenu du &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; ligne 9.&lt;/p&gt;

&lt;p&gt;Et bien… en fait, si !&lt;/p&gt;

&lt;h2 id=&quot;exécution&quot;&gt;Exécution&lt;/h2&gt;

&lt;p&gt;Essayons (j’utilise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc 4.7.2&lt;/code&gt; packagé dans &lt;em&gt;Debian Wheezy&lt;/em&gt; en &lt;em&gt;amd64&lt;/em&gt;, les
résultats peuvent différer avec un autre compilateur ou une autre version de
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt;) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ gcc -Wall undefined.c
$ ./a.out          # argc == 1
Erreur de segmentation
$ ./a.out hello    # argc == 2
pwnd 42
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Jusqu’ici, tout va bien. Maintenant, activons des optimisations de compilation :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ gcc -Wall -O2 undefined.c
$ ./a.out          # argc == 1
pwnd 42
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Voilà, nous avons réussi à exécuter le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; alors que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argc == 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Que s’est-il passé ?&lt;/p&gt;

&lt;h2 id=&quot;assembleur&quot;&gt;Assembleur&lt;/h2&gt;

&lt;p&gt;Pour le comprendre, il faut regarder le code généré en assembleur, sans et avec
optimisations.&lt;/p&gt;

&lt;h3 id=&quot;sans-optimisation&quot;&gt;Sans optimisation&lt;/h3&gt;

&lt;p&gt;Pour générer le résultat de la compilation sans assembler (et donc obtenir un fichier source assembleur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined.s&lt;/code&gt;) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gcc &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; undefined.c&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;J’ai commenté les parties importantes :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-nasm&quot; data-lang=&quot;nasm&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;nf&quot;&gt;.file&lt;/span&gt;   &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;undefined.c&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.rodata&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LC0:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.string&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pwnd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.text&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.globl&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.type&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;function&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;main:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LFB0:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_startproc&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;pushq&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_register&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;subq&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;cmpl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;; if (argc == 1)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;je&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;.L2&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;;     goto .L2&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; arg0 = 4  // sizeof(int)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;malloc&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; tmp = malloc(4)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;jmp&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.L3&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;; goto .L3&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L2:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L3:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; i = tmp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; *i = 42&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;cmpq&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;; if (!i)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;jne&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.L4&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;;    goto .L4&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; ret = 1&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;jmp&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.L5&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L4:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; arg1 = *i&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.LC0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; arg0 points to &quot;pwnd %d\n&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;printf&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; printf(&quot;pwnd %d\n&quot;, *i)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; ret = 0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L5:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;leave&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ret&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;; return ret&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_endproc&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LFE0:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.size&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.ident&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GCC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Debian&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.7&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.7&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.note.GNU&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le code généré est très fidèle au code source C.&lt;/p&gt;

&lt;h3 id=&quot;avec-gcc--o&quot;&gt;Avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -O&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Maintenant, activons certaines optimisations :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gcc &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; undefined.c&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ce qui donne :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-nasm&quot; data-lang=&quot;nasm&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;nf&quot;&gt;.file&lt;/span&gt;   &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;undefined.c&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.rodata.str1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aMS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LC0:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.string&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pwnd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.text&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.globl&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.type&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;function&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;main:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LFB11:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_startproc&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;cmpl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; if (argc == 1)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;je&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;.L2&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;;    goto .L2&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;subq&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; arg0 = 4  // sizeof(int)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;malloc&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; tmp = malloc(4)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rdx&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; i = tmp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; *i = 42&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; ret = 1&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;testq&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rdx&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; if (!i)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;je&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;.L5&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;;    goto .L5&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;; arg1 = 42&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.LC0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; arg0 points to &quot;pwnd %d\n&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;printf&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; printf(&quot;pwnd %d\n&quot;, 42)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; ret = 0&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;jmp&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.L5&lt;/span&gt;                   &lt;span class=&quot;c1&quot;&gt;; goto .L5&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L2:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; segfault (dereference addr 0)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; ret = 1&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ret&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L5:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;addq&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ret&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;; return ret&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_endproc&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LFE11:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.size&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.ident&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GCC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Debian&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.7&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.7&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.note.GNU&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Là, le compilateur a réorganisé le code. Si je devais le retraduire en C,
j’écrirais ceci :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;malloc.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pwnd %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ce qui est amusant, c’est qu’il alloue de la mémoire pour stocker &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;, il lui
affecte la valeur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt;… mais ne la lit jamais. En effet, il a décidé de recoder
en dur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt; pour le paramètre du &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mais avec ce résultat, impossible d’atteindre le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; si &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argc == 1&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;avec-gcc--o2&quot;&gt;Avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -O2&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Optimisons davantage :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gcc &lt;span class=&quot;nt&quot;&gt;-O2&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; undefined.c&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ou, plus précisément (avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc 4.9.1&lt;/code&gt; par exemple, l’option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O2&lt;/code&gt; ne suffit
pas) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gcc &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ftree-vrp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-fdelete-null-pointer-checks&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; undefined.c&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(les options d’optimisation sont décrites dans la &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html&quot;&gt;doc&lt;/a&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-nasm&quot; data-lang=&quot;nasm&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;nf&quot;&gt;.file&lt;/span&gt;   &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;undefined.c&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.rodata.str1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aMS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LC0:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.string&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pwnd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.text.startup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.p2align&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.globl&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.type&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;function&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;main:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LFB11:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_startproc&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;subq&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;; arg1 = 42&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.LC0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; arg2 points to &quot;pwnd %d\n&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;xorl&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;printf&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; printf(&quot;pwnd %d\n&quot;, 42)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;xorl&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; ret = 0&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;addq&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ret&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;; return ret&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_endproc&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LFE11:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.size&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.ident&lt;/span&gt;  &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GCC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Debian&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.7&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.7&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.note.GNU&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Là, l’optimisation donne un résultat beaucoup plus direct :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pwnd %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Quel raisonnement a-t-il pu suivre pour obtenir ce résultat ? Par exemple le
suivant.&lt;/p&gt;

&lt;p&gt;Lorsqu’il rencontre la ligne 6 de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined.c&lt;/code&gt;, soit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; est &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;, soit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;
n’est pas &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;. Le compilateur sait que déréférencer un pointeur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; est
&lt;em&gt;indéfini&lt;/em&gt;. Il n’a donc pas à gérer ce cas. Il considère donc que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; est
forcément non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mais alors, à quoi bon tester si &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; est non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; ligne 7 ? Le test ne sert à
rien. Donc il le supprime.&lt;/p&gt;

&lt;p&gt;Ce raisonnement permet de transformer le code ainsi :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;malloc.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pwnd %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais ce n’est pas tout. Le compilateur sait que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; n’est pas &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;, donc il
peut considérer que le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; a lieu. Et allouer un entier en mémoire, écrire
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt; dedans, puis lire la valeur cet entier plus tard, ça se simplifie
beaucoup : juste lire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt;, sans allouer de mémoire.&lt;/p&gt;

&lt;p&gt;Ce qu’il simplifie en :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pwnd %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 42&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;CQFD.&lt;/p&gt;

&lt;h3 id=&quot;avec-clang--02&quot;&gt;Avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clang -02&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Il est intéressant d’observer ce que produit un autre compilateur : &lt;a href=&quot;https://fr.wikipedia.org/wiki/Clang&quot;&gt;Clang&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;clang &lt;span class=&quot;nt&quot;&gt;-O2&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; undefined.c&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Voici le résultat :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-nasm&quot; data-lang=&quot;nasm&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;    &lt;span class=&quot;nf&quot;&gt;.file&lt;/span&gt;   &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;undefined.c&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.text&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.globl&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.align&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x90&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.type&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;function&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;main:&lt;/span&gt;                                   &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Ltmp2:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_startproc&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;BB#0:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;pushq&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Ltmp3:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_offset&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Ltmp4:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Ltmp5:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_def_cfa_register&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;cmpl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; if (argc == 1)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;je&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;.LBB0_4&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;;     goto .LBB0_4&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;BB#1:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; arg0 = 4  //sizeof(int)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;callq&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;malloc&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; tmp = malloc(4)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rcx&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; i = tmp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rcx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; *i = 42&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;; ret = 1&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;testq&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rcx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rcx&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; if (!i)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;je&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;.LBB0_3&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;;     goto .LBB0_3&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;BB#2:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.L.str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;; arg0 points to &quot;pwnd %d\n&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;movl&lt;/span&gt;    &lt;span class=&quot;kc&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;; arg1 = 42&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;xorb&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;al&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;al&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;callq&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;printf&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; printf(&quot;pwnd %d\n&quot;, *i)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;xorl&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;; ret = 0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LBB0_3:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;popq&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rbp&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ret&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;; return ret&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.LBB0_4:&lt;/span&gt;                                &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.thread&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;ud2&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;; undefined instruction&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Ltmp6:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.size&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;.Ltmp6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Ltmp7:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.cfi_endproc&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.Leh_func_end0:&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;.type&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;.L.str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;object&lt;/span&gt;          &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.str&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;.rodata.str1.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;aMS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.L.str:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.asciz&lt;/span&gt;   &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pwnd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.size&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;.L.str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;


    &lt;span class=&quot;nf&quot;&gt;.section&lt;/span&gt;    &lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;.note.GNU&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;progbits&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Il réalise les mêmes optimisations que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -O&lt;/code&gt;, sauf qu’il génère une erreur
explicite grâce à l’instruction machine
&lt;a href=&quot;https://en.wikipedia.org/wiki/X86_instruction_listings#Added_with_Pentium_Pro&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ud2&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;malloc.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ud2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* hardware undefined instruction */&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pwnd %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Étonnamment, &lt;em&gt;Clang&lt;/em&gt; ne prend jamais la décision de supprimer le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Par contre, avec une version suffisamment récente (ça marche avec &lt;em&gt;Clang
3.5.0&lt;/em&gt;), il est possible d’ajouter des &lt;a href=&quot;http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation&quot;&gt;vérifications lors de
l’exécution&lt;/a&gt; :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ clang -fsanitize=null undefined.c &amp;amp;&amp;amp; ./a.out
undefined.c:6:5: runtime error: store to null pointer of type &apos;int&apos;
Erreur de segmentation
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ça peut être pratique pour détecter des problèmes. Et puis des
&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/lang/NullPointerException.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NullPointerException&lt;/code&gt;&lt;/a&gt;s en C, ça fait rêver, non ?&lt;/p&gt;

&lt;h2 id=&quot;à-retenir&quot;&gt;À retenir&lt;/h2&gt;

&lt;p&gt;Si un programme contient un &lt;em&gt;comportement indéfini&lt;/em&gt;, alors son comportement
&lt;strong&gt;est&lt;/strong&gt; &lt;em&gt;indéfini&lt;/em&gt;. Pas juste la ligne en question. Pas juste les lignes qui
suivent la ligne en question. Le programme. Même s’il fonctionne maintenant sur
votre machine avec votre version de compilateur.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Somebody once told me that in basketball you can’t hold the ball and run. I
got a basketball and tried it and it worked just fine. He obviously didn’t
understand basketball.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;a href=&quot;http://www.eskimo.com/~scs/readings/undef.950311.html&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Pour aller plus loin et étudier d’autres exemples, je vous recommande la lecture
des articles suivants (en anglais) :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.regehr.org/archives/213&quot;&gt;A Guide to Undefined Behavior in C and C++&lt;/a&gt; | &lt;a href=&quot;http://blog.regehr.org/archives/226&quot;&gt;2&lt;/a&gt; |
&lt;a href=&quot;http://blog.regehr.org/archives/232&quot;&gt;3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html&quot;&gt;What Every C Programmer Should Know About Undefined Behavior&lt;/a&gt; |
&lt;a href=&quot;http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html&quot;&gt;2&lt;/a&gt; | &lt;a href=&quot;http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html&quot;&gt;3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pdos.csail.mit.edu/papers/ub:apsys12.pdf&quot;&gt;Undefined Behavior: What Happened to My Code?&lt;/a&gt; (pdf)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;optimisations-multi-threadées&quot;&gt;Optimisations multi-threadées&lt;/h2&gt;

&lt;p&gt;Les &lt;em&gt;comportements indéfinis&lt;/em&gt; font partie intégrante du &lt;em&gt;C&lt;/em&gt; et du &lt;em&gt;C++&lt;/em&gt;. Mais
même dans des langages de plus haut niveau, il existe des comportements
&lt;em&gt;indéfinis&lt;/em&gt; (pas de même nature, je vous l’accorde), notamment lorsque plusieurs
&lt;a href=&quot;https://fr.wikipedia.org/wiki/Thread_%28informatique%29&quot;&gt;threads&lt;/a&gt; s’exécutent en parallèle.&lt;/p&gt;

&lt;p&gt;Pour garantir certains comportements, il faut utiliser des mécanismes de
&lt;a href=&quot;https://en.wikipedia.org/wiki/Synchronization_%28computer_science%29&quot;&gt;synchronisation&lt;/a&gt;. Dans une vie antérieure, j’avais
&lt;a href=&quot;http://rom.developpez.com/java-synchronisation/&quot;&gt;présenté&lt;/a&gt; certains de ces mécanismes en &lt;a href=&quot;https://fr.wikipedia.org/wiki/Java_%28langage%29&quot;&gt;Java&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mais une erreur courante est de penser que la synchronisation ne fait que
garantir l’&lt;a href=&quot;https://fr.wikipedia.org/wiki/Atomicit%C3%A9_%28informatique%29&quot;&gt;atomicité&lt;/a&gt; avec des &lt;a href=&quot;https://fr.wikipedia.org/wiki/Section_critique&quot;&gt;sections critiques&lt;/a&gt;. En réalité, c’est plus
complexe que cela. D’une part, elle ajoute des &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_barrier&quot;&gt;barrières mémoire&lt;/a&gt; empêchant
certaines réorganisations des instructions (ce qui explique pourquoi le
&lt;a href=&quot;https://fr.wikipedia.org/wiki/Double-checked_locking&quot;&gt;double-checked locking&lt;/a&gt; pour écrire des &lt;a href=&quot;https://fr.wikipedia.org/wiki/Singleton_%28patron_de_conception%29&quot;&gt;singletons&lt;/a&gt; est &lt;a href=&quot;http://www.javamex.com/tutorials/double_checked_locking.shtml&quot;&gt;faux&lt;/a&gt;).
D’autre part, elle permet de synchroniser les caches locaux des threads, sans
quoi l’exemple suivant (inspiré d’&lt;a href=&quot;http://stackoverflow.com/questions/5022100/when-does-java-thread-cache-refresh-happens/5022188#5022188&quot;&gt;ici&lt;/a&gt;) est incorrect :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VisibilityTest&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keepRunning&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;VisibilityTest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VisibilityTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;keepRunning&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentTimeMillis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                           &lt;span class=&quot;s&quot;&gt;&quot;: keepRunning false&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentTimeMillis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;: start&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keepRunning&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentTimeMillis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;: end&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour le compiler et l’exécuter :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;javac VisibilityTest.java &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; java VisibilityTest&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Sans synchronisation, il est très fort probable que le &lt;em&gt;thread&lt;/em&gt; démarré ne se
termine jamais, voyant toujours &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keepRunning&lt;/code&gt; à &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;, même si le thread
principal lui a donné la valeur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Là encore, c’est une optimisation (la mise en cache d’une variable) qui provoque
ce comportement “inattendu” sans &lt;a href=&quot;http://www.javamex.com/tutorials/synchronization_concurrency_synchronized2.shtml&quot;&gt;synchronisation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Déclarer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keepRunning&lt;/code&gt; &lt;a href=&quot;http://www.javamex.com/tutorials/synchronization_volatile.shtml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;volatile&lt;/code&gt;&lt;/a&gt; suffit à résoudre le problème.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;La notion de &lt;em&gt;comportement indéfini&lt;/em&gt; est très importante pour améliorer la
performance des programmes. Mais elle est source de bugs parfois difficiles à&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Erreur de segmentation&lt;/code&gt;&lt;/p&gt;
</content>
 </entry>
  
 
  
 
  
   
 <entry>
   <title>Chiffrer un disque dur externe (ou une clé USB) avec LUKS</title>
   <link href="https://blog.rom1v.com/2014/07/chiffrer-un-disque-dur-externe-ou-une-cle-usb-avec-luks/"/>
   <updated>2014-07-20T21:03:33+02:00</updated>
   <id>https://blog.rom1v.com/2014/07/chiffrer-un-disque-dur-externe-ou-une-cle-usb-avec-luks</id>
   <content type="html">&lt;p&gt;Un disque dur externe contenant vos données n’a pas de raisons de ne pas être
chiffré. Voici quelques commandes utiles pour l’utilisation de &lt;a href=&quot;http://fr.wikipedia.org/wiki/LUKS&quot;&gt;LUKS&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;prérequis&quot;&gt;Prérequis&lt;/h2&gt;

&lt;p&gt;Le paquet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cryptsetup&lt;/code&gt; doit être installé :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cryptsetup&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;initialisation&quot;&gt;Initialisation&lt;/h2&gt;

&lt;h3 id=&quot;trouver-le-disque&quot;&gt;Trouver le disque&lt;/h3&gt;

&lt;p&gt;Tout d’abord, il faut déterminer l’emplacement du disque dur dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev&lt;/code&gt;. Pour
cela, avant de le brancher, exécuter la commande :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /var/log/messages&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Lors du branchement du disque, plusieurs lignes similaires à celles-ci doivent
apparaître :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Jul 20 21:25:29 pc kernel: [  678.139988] sd 7:0:0:0: [sdb] 976754645 4096-byte logical blocks: (4.00 TB/3.63 TiB)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ici, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[sdb]&lt;/code&gt; signifie que l’emplacement est &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sdb&lt;/code&gt;. Dans la suite, je
noterai cet emplacement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/XXX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Il est très important de ne pas se tromper d’emplacement, afin de ne pas
formater un autre disque…&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;effacer-le-disque&quot;&gt;Effacer le disque&lt;/h3&gt;

&lt;p&gt;Si des données étaient présentes sur ce disque, il est plus sûr de tout
supprimer physiquement :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/XXX &lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4K&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Cette commande peut prendre beaucoup de temps, puisqu’elle consiste à réécrire
physiquement tous les octets du disque dur.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;créer-la-partition-chiffrée&quot;&gt;Créer la partition chiffrée&lt;/h3&gt;

&lt;p&gt;Pour initialiser la partition chiffrée :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksFormat &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt; sha256 /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;La passphrase de déchiffrement sera demandée.&lt;/p&gt;

&lt;p&gt;Maintenant que nous avons une partition chiffrée, ouvrons-la :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksOpen /dev/XXX lenomquevousvoulez&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Cette commande crée un nouveau &lt;em&gt;device&lt;/em&gt; dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/mapper/lenomquevousvoulez&lt;/code&gt;,
contenant la version déchiffrée (en direct).&lt;/p&gt;

&lt;h3 id=&quot;formater&quot;&gt;Formater&lt;/h3&gt;

&lt;p&gt;Pour formater cette partition en &lt;a href=&quot;https://fr.wikipedia.org/wiki/Ext4&quot;&gt;ext4&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mkfs.ext4 /dev/mapper/lenomquevousvoulez &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; unlabel&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour l’initialisation, c’est fini, nous pouvons fermer la vue déchiffrée :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksClose lenomquevousvoulez&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;montage-manuel&quot;&gt;Montage manuel&lt;/h2&gt;

&lt;p&gt;Il est possible de déchiffrer et monter la partition manuellement en ligne de commande :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksOpen /dev/XXX lenomquevousvoulez
&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /media/mydisk
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; ext4 /dev/mapper/lenomquevousvoulez /media/mydisk&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Le contenu est alors accessible dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/media/mydisk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pour démonter et fermer, c’est le contraire :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;umount /media/mydisk
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksClose /dev/XXX lenomquevousvoulez&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais c’est un peu fastidieux. Et je n’ai pas trouvé de solution pour permettre
le &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;luksOpen&lt;/code&gt; par un utilisateur (non-root) en ligne de commande.&lt;/p&gt;

&lt;h2 id=&quot;montage-semi-automatique&quot;&gt;Montage semi-automatique&lt;/h2&gt;

&lt;p&gt;Les environnement de bureau permettent parfois de monter un disque dur chiffré
simplement, avec la demande de la passphrase lors de l’ouverture du disque.
Voici ce que j’obtiens avec &lt;a href=&quot;http://www.xfce.org/&quot;&gt;XFCE&lt;/a&gt; :&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/assets/luks/luksOpen.png&quot; alt=&quot;luksOpen&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mais par défaut, le nom du point de montage est peu pratique : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/media/rom/ae74bc79-9efe-4325-8b4d-63d1506fa928&lt;/code&gt;. Heureusement, il est possible de le changer. Pour cela, il faut déterminer le nom de la partition déchiffrée :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls /dev/mapper/luks-*
/dev/mapper/luks-8b927433-4d4f-4636-8a76-06d18c09723e
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Le nom très long correspond en fait à l’UUID du disque, qui peut aussi être récupéré grâce à :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksUUID /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;ou encore :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;blkid /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;L’emplacement désiré, ainsi que les options qui-vont-bien, doivent être rajoutés
dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt; :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/dev/mapper/luks-8b927433-4d4f-4636-8a76-06d18c09723e /media/mydisk ext4 user,noauto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ainsi, le disque sera désormais monté dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/media/mydisk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si en plus, nous souhaitons spécifier un nom &lt;em&gt;user-friendly&lt;/em&gt; pour la partition
déchiffrée (celui dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/mapper/&lt;/code&gt;), il faut ajouter une ligne dans
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt; (en adaptant l’UUID) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mydisk UUID=8b927433-4d4f-4636-8a76-06d18c09723e none luks,noauto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Et utiliser celle-ci à la place dans &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt; :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/dev/mapper/mydisk /media/mydisk ext4 user,noauto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;gestion-des-passphrases&quot;&gt;Gestion des passphrases&lt;/h2&gt;

&lt;p&gt;Il est possible d’utiliser plusieurs passphrases (jusqu’à 8) pour déchiffrer le
même disque.&lt;/p&gt;

&lt;p&gt;Pour en ajouter une :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksAddKey /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour en supprimer une :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksRemoveKey /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour changer une unique passphrase, il suffit d’en ajouter une nouvelle puis de
supprimer l’ancienne.&lt;/p&gt;

&lt;p&gt;Ou alors d’utiliser :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksChangeKey /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;mais &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man cryptsetup&lt;/code&gt; dit qu’il y a un risque.&lt;/p&gt;

&lt;h2 id=&quot;état&quot;&gt;État&lt;/h2&gt;

&lt;p&gt;Pour consulter l’état d’une partition LUKS :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;cryptsetup luksDump /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;gestion-de-len-tête&quot;&gt;Gestion de l’en-tête&lt;/h2&gt;

&lt;p&gt;L’en-tête LUKS est écrit au début du disque. L’écraser empêche définivement le
déchiffrement de la partition.&lt;/p&gt;

&lt;p&gt;Il est possible d’en faire une sauvegarde dans un fichier :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cryptsetup luksHeaderBackup /dev/XXX &lt;span class=&quot;nt&quot;&gt;--header-backup-file&lt;/span&gt; fichier&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Et de les restaurer :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cryptsetup luksHeaderRestore /dev/XXX &lt;span class=&quot;nt&quot;&gt;--header-backup-file&lt;/span&gt; fichier&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pour supprimer l’en-tête (et donc rendre les données définitivement
inaccessibles s’il n’y a pas de backup) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cryptsetup luksErase /dev/XXX&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Une fois configuré la première fois, et après les quelques modifications
pénibles pour choisir les noms pour le déchiffrement et le montage,
l’utilisation au quotidien est vraiment très simple : il suffit de rentrer la
passphrase directement à partir du navigateur de fichiers.&lt;/p&gt;
</content>
 </entry>
  
 
  
   
 <entry>
   <title>SSHFS inversé (rsshfs)</title>
   <link href="https://blog.rom1v.com/2014/06/sshfs-inverse-rsshfs/"/>
   <updated>2014-06-15T13:30:27+02:00</updated>
   <id>https://blog.rom1v.com/2014/06/sshfs-inverse-rsshfs</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/SSHFS&quot;&gt;SSHFS&lt;/a&gt; permet de monter un répertoire d’une machine distance dans
l’arborescence locale en utilisant &lt;a href=&quot;https://fr.wikipedia.org/wiki/Secure_Shell&quot;&gt;SSH&lt;/a&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sshfs serveur:/répertoire/distant /répertoire/local&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mais &lt;strong&gt;comment monter un répertoire local sur une machine distante ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Une solution simple serait de se connecter en &lt;em&gt;SSH&lt;/em&gt; sur la machine distante et
d’exécuter la commande &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sshfs&lt;/code&gt; classique.&lt;/p&gt;

&lt;p&gt;Mais d’abord, ce n’est pas toujours directement &lt;strong&gt;possible&lt;/strong&gt; : la machine locale
peut ne pas être accessible (non adressable) depuis la machine distante. &lt;em&gt;Ça se
contourne en créant un tunnel SSH utilisant la redirection de port distante
(option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Et surtout, ce n’est pas toujours &lt;strong&gt;souhaitable&lt;/strong&gt; : cela nécessite que la clé
privée autorisée sur la machine locale soit connue de la machine distante. Or,
dans certains cas, nous ne voulons pas qu’une machine &lt;em&gt;esclave&lt;/em&gt; puisse se
connecter à notre machine &lt;em&gt;maître&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;reverse-sshfs&quot;&gt;Reverse SSHFS&lt;/h2&gt;

&lt;p&gt;En me basant sur &lt;a href=&quot;https://sourceforge.net/p/fuse/mailman/message/27034864/&quot;&gt;la commande donnée en exemple&lt;/a&gt;, j’ai donc écrit un
petit script &lt;em&gt;Bash&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsshfs&lt;/code&gt;, licence &lt;a href=&quot;http://www.gnu.org/licenses/quick-guide-gplv3.fr.html&quot;&gt;GPLv3&lt;/a&gt;) qui permet le &lt;em&gt;reverse
SSHFS&lt;/em&gt; : &lt;a href=&quot;https://github.com/rom1v/rsshfs&quot;&gt;rsshfs&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git clone https://github.com/rom1v/rsshfs
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;rsshfs
&lt;span class=&quot;nb&quot;&gt;sudo install &lt;/span&gt;rsshfs /usr/local/bin&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Les paquets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sshfs&lt;/code&gt; et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fuse&lt;/code&gt; doivent être installés sur la machine distante
(et l’utilisateur doit appartenir au groupe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fuse&lt;/code&gt;). Le paquet
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssh-sftp-server&lt;/code&gt; doit être installé sur la machine locale.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Son utilisation se veut similaire à celle de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sshfs&lt;/code&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;rsshfs /répertoire/local serveur:/répertoire/distant&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Comme avec &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sshfs&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/répertoire/distant&lt;/code&gt; doit exister sur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serveur&lt;/code&gt; et doit
être vide.&lt;/p&gt;

&lt;p&gt;Il est également possible de monter le répertoire en &lt;em&gt;lecture seule&lt;/em&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;rsshfs /répertoire/local serveur:/répertoire/distant &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ro&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Contrairement à &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sshfs&lt;/code&gt;, étant donné que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsshfs&lt;/code&gt; agit comme un serveur, cette
commande ne retourne pas tant que le répertoire distant n’est pas démonté.&lt;/p&gt;

&lt;p&gt;Pour démonter, dans un autre terminal :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;rsshfs &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; serveur:/répertoire/distant&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ou plus simplement en pressant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+C&lt;/code&gt; dans le terminal de la commande de
montage.&lt;/p&gt;

&lt;h2 id=&quot;amélioration&quot;&gt;Amélioration&lt;/h2&gt;

&lt;p&gt;J’ai choisi la facilité en écrivant un script indépendant qui appelle la
commande qui-va-bien.&lt;/p&gt;

&lt;p&gt;L’idéal serait d’ajouter cette fonctionnalité à &lt;a href=&quot;https://github.com/libfuse/sshfs&quot;&gt;sshfs&lt;/a&gt;
directement.&lt;/p&gt;

</content>
 </entry>
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 

</feed>
