Nous utilisons quotidiennement les compilateurs comme si leur exactitude était acquise, mais les compilateurs sont aussi des programmes et peuvent potentiellement contenir des bogues. Je me suis toujours interrogé sur cette robustesse infaillible. Avez-vous déjà rencontré un bogue dans le compilateur lui-même? Qu'est-ce que c'était et comment avez-vous réalisé que le problème était dans le compilateur lui-même?
... et comment rendent- ils les compilateurs si fiables?
testing
bug
compiler
system-reliability
EpsilonVector
la source
la source
Réponses:
Ils sont testés de manière approfondie via des milliers, voire des millions de développeurs, au fil du temps.
De plus, le problème à résoudre est bien défini (par une spécification technique très détaillée). Et la nature de la tâche se prête facilement aux tests unitaires / système. C'est-à-dire qu'il s'agit essentiellement de traduire une entrée textuelle dans un format très spécifique pour une sortie dans un autre type de format bien défini (une sorte de code octet ou de code machine). Il est donc facile de créer et de vérifier des cas de test.
De plus, les bogues sont généralement faciles à reproduire: hormis les informations exactes sur la plate-forme et la version du compilateur, vous n'avez généralement besoin que d'un morceau de code d'entrée. Sans compter que les utilisateurs du compilateur (étant les développeurs eux-mêmes) ont tendance à donner des rapports de bogues beaucoup plus précis et détaillés que tout utilisateur d'ordinateur moyen :-)
la source
En plus de toutes les bonnes réponses à ce jour:
Vous avez un "biais d'observateur". Vous n'observez pas de bugs et vous supposez donc qu'il n'y en a pas.
Je pensais comme toi. Ensuite, j'ai commencé à écrire des compilateurs de manière professionnelle, et laissez-moi vous dire qu'il y a beaucoup de bugs là-dedans!
Vous ne voyez pas les bogues parce que vous écrivez un code équivalent à 99,999% du reste du code écrit. Vous écrivez probablement du code parfaitement normal, simple et clairement correct, qui appelle des méthodes et exécute des boucles sans rien faire de bizarre ou bizarre, car vous êtes un développeur normal qui résout des problèmes commerciaux normaux.
Vous ne voyez pas de bogues de compilateur, car ceux-ci ne figurent pas dans les scénarios de code normaux simples à analyser et faciles à analyser; les bugs sont dans l'analyse de code étrange que vous n'écrivez pas.
J'ai par contre le biais d'observateur opposé. Je vois du code fou toute la journée, et donc pour moi, les compilateurs semblent fourmiller de bogues.
Si vous vous assoyiez avec la spécification de langue de n'importe quel langage et preniez n'importe quelle implémentation de compilateur pour ce langage, et essayiez vraiment de déterminer si le compilateur implémentait exactement la spécification ou non, en vous concentrant sur des cas obscurs, vous découvririez bientôt compilateur des bogues assez fréquemment. Laissez-moi vous donner un exemple, voici un bogue du compilateur C # que j'ai trouvé littéralement il y a cinq minutes.
Le compilateur donne trois erreurs.
De toute évidence, le premier message d'erreur est correct et le troisième est un bogue. L'algorithme de génération d'erreur essaie de comprendre pourquoi le premier argument était invalide, il l'examine, voit qu'il s'agit d'une constante et ne retourne pas dans le code source pour vérifier s'il a été marqué "ref"; il suppose plutôt que personne ne serait assez idiot pour marquer une constante comme arbitre et décide que l'arbitre doit être manquant.
Le troisième message d'erreur correct n'est pas clair, mais ce n'est pas ça. En fait, il n'est pas clair si le deuxième message d'erreur est correct non plus. La résolution de surcharge doit-elle échouer ou "ref 123" doit-il être traité comme un argument de référence du type correct? Je vais maintenant devoir y réfléchir et en discuter avec l'équipe de triage afin que nous puissions déterminer quel est le bon comportement.
Vous n'avez jamais vu ce bug parce que vous ne feriez probablement jamais quelque chose d'aussi stupide que d'essayer de passer 123 par réf. Et si vous le faisiez, vous ne remarqueriez probablement même pas que le troisième message d'erreur est absurde, car le premier message est correct et suffisant pour diagnostiquer le problème. Mais j'essaie de faire des choses comme ça, parce que j'essaye de casser le compilateur. Si vous essayiez, vous verriez aussi les bugs.
la source
Vous plaisantez j'espère? Les compilateurs ont aussi des bugs, des charges vraiment.
GCC est probablement le compilateur open source le plus célèbre de la planète et jetez un œil à sa base de données de bogues: http://gcc.gnu.org/bugzilla/buglist.cgi?product=gcc&component=c%2B%2B&resolution=-- -
Entre GCC 3.2 et GCC 3.2.3, regardez combien de bogues ont été corrigés: http://gcc.gnu.org/gcc-3.2/changes.html
Pour d'autres, comme Visual C ++, je ne veux même pas commencer.
Comment faites-vous des compilateurs fiables? Eh bien pour commencer, ils ont des charges et des charges de tests unitaires. Et la planète entière les utilise donc pas de pénurie de testeurs.
Sérieusement, les concepteurs de compilateur que j’aime croire sont des programmeurs de haut niveau et, bien qu’ils ne soient pas infaillibles, ils sont très efficaces.
la source
J'ai rencontré deux ou trois dans ma journée. Le seul moyen de le détecter consiste à consulter le code de l'ensemble.
Bien que les compilateurs soient très fiables pour les raisons indiquées par d'autres affiches, je pense que la fiabilité des compilateurs est souvent une évaluation auto-réalisatrice. Les programmeurs ont tendance à considérer le compilateur comme la norme. Lorsque quelque chose ne va pas, vous assumez que c'est votre faute (parce que c'est 99,999% du temps) et vous modifiez votre code pour résoudre le problème du compilateur plutôt que l'inverse. Par exemple, le crash de code sous un paramètre d'optimisation élevé est sans aucun doute un bogue du compilateur, mais la plupart des gens le règlent un peu plus bas et passent à autre chose sans signaler le bogue.
la source
Les compilateurs ont plusieurs propriétés qui conduisent à leur exactitude:
la source
Ils ne le font pas. Nous faisons. Parce que tout le monde les utilise tout le temps, les bugs se trouvent rapidement.
C'est un jeu de nombres. Étant donné que les compilateurs sont utilisés de manière omniprésente, il est fort probable que tout bogue sera provoqué par quelqu'un, mais étant donné le nombre élevé d'utilisateurs, il est très peu probable que quelqu'un vous soit spécifiquement.
Cela dépend donc de votre point de vue: les compilateurs sont bogués pour tous les utilisateurs. Mais il est très probable que quelqu'un d' autre aura compilé un morceau similaire de code avant que vous avez fait, si leur était un bug, il aurait les frapper, pas vous, donc de votre personne point de vue, il semble que le bug était jamais là.
Bien entendu, vous pouvez ajouter toutes les autres réponses ici: les compilateurs sont bien documentés, bien compris. Il y a ce mythe selon lequel ils sont difficiles à écrire, ce qui signifie que seuls les très bons et très bons programmeurs tentent réellement d'en écrire un, et font très attention quand ils le font. Ils sont généralement faciles à tester et faciles à tester ou à tester. Les utilisateurs de compilateur ont tendance à être eux-mêmes des programmeurs experts, ce qui conduit à des rapports de bogue de haute qualité. Et l’inverse: les auteurs de compilateur ont tendance à utiliser leur propre compilateur.
la source
En plus de toutes les réponses déjà, j'aimerais ajouter:
Je crois souvent que les vendeurs mangent leur propre nourriture pour chiens. Cela signifie qu'ils écrivent les compilateurs eux-mêmes.
la source
J'ai souvent rencontré des bogues de compilation.
Vous pouvez les trouver dans les coins les plus sombres où il y a moins de testeurs. Par exemple, pour trouver des bogues dans GCC, vous devriez essayer:
la source
Plusieurs raisons:
la source
Ils sont généralement très bons à -O0. En fait, si nous suspectons un bogue du compilateur, nous comparons -O0 au niveau que nous essayons d'utiliser. Des niveaux d'optimisation plus élevés comportent un risque plus élevé. Certains le sont même délibérément, et étiquetés comme tels dans la documentation. J'en ai rencontré beaucoup (au moins une centaine à mon époque), mais ces dernières sont de plus en plus rares. Néanmoins, à la recherche de bons numéros de point de repère (ou d’autres références importantes pour le marketing), la tentation de repousser les limites est grande. Il y a quelques années, nous avons eu des problèmes lorsqu'un fournisseur (pour rester anonyme) a décidé de violer la parenthèse par défaut, plutôt qu'une option de compilation spéciale clairement identifiée.
Il peut être difficile de diagnostiquer une erreur du compilateur par opposition à une référence de mémoire parasite, une recompilation avec différentes options peut simplement brouiller le positionnement relatif des objets de données dans la mémoire, de sorte que vous ne savez pas s'il s'agit de Heisenbug de votre code source ou d'un buggy. compilateur. De plus, de nombreuses optimisations apportent des modifications légitimes à l'ordre des opérations, voire des simplifications algébriques à votre algèbre. Celles-ci auront des propriétés différentes en ce qui concerne l'arrondi en virgule flottante et les dépassements inférieurs / supérieurs. Il est difficile de distinguer ces effets des vrais bugs. C'est pour cette raison que l'informatique en virgule flottante est difficile, car les bugs et la sensibilité numérique ne sont souvent pas faciles à démêler.
la source
Les bogues du compilateur ne sont pas si rares. Le cas le plus courant est qu'un compilateur signale une erreur sur un code devant être accepté ou un compilateur accepte un code qui aurait dû être rejeté.
la source
Oui, j'ai rencontré un bogue dans le compilateur ASP.NET hier:
Lorsque vous utilisez des modèles fortement typés dans les vues, le nombre de paramètres que les modèles peuvent contenir est limité. Évidemment, il ne peut prendre plus de 4 paramètres de modèle, de sorte que les deux exemples ci-dessous rendent le compilateur trop difficile à gérer:
Ne compilerait pas tel quel, mais sera si
type5
est supprimé.Compilerait si
type4
est supprimé.Notez que cela
System.Tuple
a beaucoup de surcharges et peut prendre jusqu'à 16 paramètres (c'est fou je sais).la source
Ouaip!
Les deux plus mémorables sont les deux premiers que j'ai rencontrés. Ils étaient tous deux dans le compilateur Lightspeed C pour 680x0 Macs vers 1985-7.
La première concernait les cas où, dans certaines circonstances, l'opérateur de postincrément entier ne faisait rien - autrement dit, dans un morceau de code particulier, "i ++" ne faisait tout simplement rien pour "i". Je tirais mes cheveux jusqu'à ce que je regarde un démontage. Ensuite, j'ai simplement incrémenté différemment et soumis un rapport de bogue.
La seconde était un peu plus compliquée, et était une "fonctionnalité" mal réfléchie qui a mal tourné. Les premiers Mac avaient un système compliqué pour effectuer des opérations de disque de bas niveau. Pour une raison quelconque, je n'ai jamais compris - probablement en rapport avec la création d'exécutables plus petits - plutôt que le compilateur générant simplement les instructions d'opération de disque sur place dans le code d'objet, le compilateur Lightspeed appelle une fonction interne qui, au moment de l'exécution, génère l'opération de disque. instructions sur la pile et y ont sauté.
Cela fonctionnait très bien sur 68000 processeurs, mais lorsque vous exécutiez le même code sur un processeur 68020, il faisait souvent des choses étranges. Il s'est avéré qu'une nouvelle fonctionnalité du 68020 était un cache d'instruction d'instruction primitive de 256 octets. Étant donné que nous étions à l’origine des caches de CPU, il n’avait aucune idée que le cache était "sale" et devait être rempli; Je suppose que les concepteurs de CPU chez Motorola n’ont pas pensé au code à modification automatique. Par conséquent, si vous exécutez deux opérations sur le disque assez proches dans votre séquence d'exécution et que le moteur d'exécution Lightspeed construit les instructions au même endroit sur la pile, le CPU pense à tort qu'il a un cache d'instruction et exécute la première opération de disque deux fois.
Encore une fois, comprendre cela a pris un peu de temps à creuser avec un désassembleur et beaucoup de démarches simples dans un débogueur de bas niveau. Ma solution de contournement consistait à préfixer chaque opération de disque par un appel à une fonction exécutant 256 instructions "NOP", qui inondaient (et donc effaçaient) le cache d'instructions.
Au cours des 25 années qui se sont écoulées depuis, j'ai vu de moins en moins de bogues de compilateur au fil du temps. Je pense qu'il y a plusieurs raisons à cela:
la source
Trouvé une erreur flagrante dans Turbo Pascal il y a 5,5 ans. Une erreur ne figure ni dans la version précédente (5.0) ni dans la version suivante (6.0) du compilateur. Et un test qui aurait dû être facile à tester, car ce n’était pas du tout une majuscule (juste un appel qui n’est pas aussi courant).
En général, les constructeurs de compilateurs commerciaux (plutôt que les projets de loisir) disposeront de procédures d’assurance qualité et de tests très complètes. Ils savent que leurs compilateurs sont leurs projets phares et que leurs failles leur seront très mauvaises, pire qu’ils ne le feraient d’autres sociétés qui fabriquent la plupart des autres produits. Les développeurs de logiciels sont un groupe impitoyable. Nos fournisseurs d’outils nous ont laissé savoir que nous allions probablement chercher des solutions de rechange plutôt que d’attendre une solution de leur fournisseur. Nous sommes très susceptibles de le communiquer à nos pairs qui pourraient bien suivre notre exemple. Dans de nombreux autres secteurs, ce n'est pas le cas. Par conséquent, la perte potentielle pour un fabricant de compilateur à la suite d'un grave bogue est bien supérieure à celle d'un fabricant de logiciels de montage vidéo.
la source
Lorsque le comportement de votre logiciel est différent lors de la compilation avec -O0 et avec -O2, vous avez détecté un bogue du compilateur.
Lorsque le comportement de votre logiciel diffère de vos attentes, il est probable que le bogue se trouve dans votre code.
la source
Les bogues du compilateur se produisent, mais vous avez tendance à les trouver dans des coins étranges ...
Il y avait un bug étrange dans le compilateur VAX VMS C de Digital Equipment Corporation dans les années 1990
(Je portais un oignon à la ceinture, comme c'était la mode à l'époque)
Un point-virgule supplémentaire précédant n'importe quelle boucle for serait compilé en tant que corps de la boucle for.
Sur le compilateur en question, la boucle ne s'exécute qu'une fois.
il voit
Cela m'a coûté beaucoup de temps.
L'ancienne version du compilateur PIC C que nous avions l'habitude d'infliger à l'expérience de travail, nous ne pouvions pas générer de code utilisant correctement l'interruption de priorité élevée. Vous avez dû attendre 2-3 ans et mettre à niveau.
Le compilateur MSVC 6 avait un bogue astucieux dans l’éditeur de liens, il commettrait une erreur de segmentation et mourrait de temps à autre sans raison. Une construction propre l'a généralement réparée (mais ne soupire pas toujours).
la source
Dans certains domaines, tels que le logiciel avionique, les exigences en matière de certification sont extrêmement élevées, tant pour le code et le matériel que pour le compilateur. À propos de cette dernière partie, il existe un projet visant à créer un compilateur C formellement vérifié, appelé Compcert . En théorie, ce type de compilateur est aussi fiable qu’il se présente.
la source
J'ai vu plusieurs bogues du compilateur, j'en ai signalé quelques-uns (plus précisément en F #).
Cela dit, je pense que les bogues du compilateur sont rares car ceux qui écrivent des compilateurs sont généralement très à l'aise avec les concepts rigoureux de l'informatique qui les rendent vraiment conscients des implications mathématiques du code.
La plupart d'entre eux sont probablement très familiers avec des choses comme le calcul lambda, la vérification formelle, la sémantique dénotationnelle, etc., des choses qu'un programmeur moyen comme moi peut à peine comprendre.
En outre, il existe généralement un mappage assez simple entre entrée et sortie dans les compilateurs. Par conséquent, le débogage d'un langage de programmation est probablement beaucoup plus facile que le débogage, par exemple, d'un moteur de blog.
la source
J'ai trouvé un bogue dans le compilateur C # pas trop longtemps, vous pouvez voir comment Eric Lippert (qui est sur l'équipe de conception C #) a compris ce que le bug était ici .
En plus des réponses déjà données, j'aimerais ajouter quelques éléments supplémentaires. Les concepteurs de compilateurs sont souvent de très bons programmeurs. Les compilateurs sont très importants: la plupart des programmes sont réalisés à l'aide de compilateurs, il est donc impératif que le compilateur soit de haute qualité. Les entreprises qui fabriquent des compilateurs ont donc tout intérêt à y mettre leurs meilleurs collaborateurs (ou du moins de très bons: les meilleurs n’aiment peut-être pas la conception de compilateurs). Microsoft aimerait beaucoup que leurs compilateurs C et C ++ fonctionnent correctement, sinon le reste de la société ne peut pas faire son travail.
En outre, si vous construisez un compilateur très complexe, vous ne pouvez pas le pirater ensemble. La logique derrière les compilateurs est à la fois très complexe et facile à formaliser. Par conséquent, ces programmes seront souvent construits de manière très «robuste» et générique, ce qui tend à réduire le nombre de bogues.
la source