mercredi 29 janvier 2014

Have you ever encountered a compiler bug ?

Bon, c'est pas la première fois que ça m'arrive mais cette fois j'ai mis du temps à réagir... Pour préparer un nouvel article sur le C++11 je testais différentes choses autour des rvalue-references. L'article viendra plus tard donc... Finalement les problèmes rencontrés n'avaient rien à voir avec les rvalue-references, mais je m'entêtais; il a fallu du temps pour extraire la substantifique moelle. Mon exemple sur les rvalue-references essayait de montrer comment ce mécanisme permet d'optimiser le code en évitant de dupliquer trop d'objets en autorisant le contrôle des déplacements de valeur; comme les compilateurs C++ font aussi de l'élimination de copie (voir un billet précédent) je souhaitais donc supprimer la copy-elision afin d'effectuer des mesures sur un code analysable simplement par lecture de son code source. Finalement, le problème a surgit quand bien même les rvalue-references ne sont pas utilisées. Voici le code qui pose problème :
#include <iostream>
#include <string>
#include <utility>
using namespace std;

int main() {
  string s = string("11") + "22" + "33" + "44";
  cout << s << endl;

  string s2 = "11";
  cout << s2 << endl;

  string s3 = s2 + "22";
  cout << s3 << endl;
  return 0;
}
Bien entendu, les deux premières lignes sont bien suffisantes, mais j'ai laissé quelques autres petites tests mineurs.
Premier test avec une compilation ordinaire (donc avec copy-elision) :
% g++ -o rv4 rv4.cpp
% ./rv4
11223344
11
1122
Rien de mystérieux ni d'anormal. Compilons en enlevant la copy-elision :
% g++ -fno-elide-constructors -o rv4 rv4.cpp
% ./rv4

11

Comme on l'observe facilement, il y a un problème; mais l'observation n'est pas complète car cet exemple est trop épuré. Avec des structures plus complexes que les string l'effet est tout à fait surréaliste, les structures de données sont dans des états bizarres et les affichages difficilement interprétables.
Pire, en compilant en conformité avec le standard C++11, le résultat n'est pas le même!
% g++ -std=c++11 -fno-elide-constructors -o rv4 rv4.cpp
% ./rv4                                            
11223344
11

Lorsque ceci est mélangé à l'utilisation de la sémantique de déplacement (move) je vous laisse imaginer ma perplexité lorsque combiné avec un type un poil plus subtil utilisant des pointeurs et de l'allocation dynamique!
Alors quelle version de g++ est impactée ? Il semble que de nombreuses le soient. La mienne est :
% g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
%
Le rapport de bug est disponible ici. L'un des commentaires daté du 11 janvier 2014 indique que le bug a été corrigé, ce que je n'ai pu encore tester mais que je m'empresserais de faire à la prochaine mise à jour. Si vous êtes intéressé par la correction, la voici : commit.

Conclusion : doit-il y a voir une conclusion ? Peut-être que la réalité de l'informatique nous oblige à croire que nous faisons naturellement trop d'erreurs et avons donc un défaut de confiance en notre propre code, voire trop de confiance en les compilateurs. Vivement les compilateurs certifiés... Je sais il y en a et des français y travaillent : citons Xavier Leroy (ou sa page Wikipedia) et Cminor, ou quelqu'un de plus proche encore de nous : YuRuG. Ou encore, vivement des spécifications pas trop tordues pour les langages, peut-être C++ est-il arrivé dans un état qui causera sa propre perte ? ou l'enfermera dans une niche d'où il ne sortira plus ?

DjiBee

Aucun commentaire:

Enregistrer un commentaire