En tant qu’ingénieur logiciel, j’écris beaucoup de code pour les produits industriels. Trucs relativement compliqués avec des classes, des threads, des efforts de conception, mais aussi des compromis sur les performances. Je fais beaucoup de tests, et j'en ai marre, alors je me suis intéressé aux outils de preuve formels, tels que Coq, Isabelle ... Pourrais-je en utiliser un pour prouver formellement que mon code est sans bug et qu'il est prêt avec ça? - mais chaque fois que je vérifie l'un de ces outils, je ne suis pas convaincu qu'ils soient utilisables pour le génie logiciel au quotidien. Maintenant, ça ne peut être que moi, et je cherche des pointeurs / opinions / idées à ce sujet :-)
Plus précisément, j’ai l’impression que, pour que l’un de ces outils fonctionne, il faudrait un investissement considérable pour bien définir les objectifs, les méthodes ... du programme considéré. Je me demande alors si le prouveur ne s'essoufflerait pas compte tenu de l'ampleur de tout ce qui lui incomberait. Ou peut-être devrais-je me débarrasser des effets secondaires (ces outils de démonstration semblent bien fonctionner avec les langages déclaratifs), et je me demande si cela aurait pour résultat un "code éprouvé" qui ne pourrait pas être utilisé car il ne serait pas rapide ou assez petit. De plus, je n'ai pas le luxe de changer le langage avec lequel je travaille, il faut que ce soit Java ou C ++: je ne peux pas dire à mon supérieur que je vais coder en OXXXml à partir de maintenant, car c'est le seul langage en ce que je peux prouver l'exactitude du code ...
Est-ce que quelqu'un avec plus d'expérience des outils de preuve formels pourrait commenter? Encore une fois - j'adorerais utiliser un outil de démonstration formel, je les trouve géniaux, mais j'ai l'impression qu'ils se trouvent dans une tour d'ivoire que je ne peux pas atteindre depuis le petit fossé de Java / C ++ ... (PS: I J'AIME aussi Haskell, OCaml ... ne vous méprenez pas: je suis un fan des langages déclaratifs et des preuves formelles, j'essaie simplement de voir comment je pourrais concrètement rendre cela utile au génie logiciel)
Mise à jour: Puisque c'est assez large, essayons les questions plus spécifiques suivantes: 1) existe-t-il des exemples d'utilisation de prouveurs pour prouver l'exactitude des programmes industriels Java / C ++? 2) Coq conviendrait-il à cette tâche? 3) Si Coq convient, dois-je d'abord écrire le programme en Coq, puis générer C ++ / Java à partir de Coq? 4) Cette approche pourrait-elle gérer les optimisations de threading et de performance?
Réponses:
Je vais essayer de donner une réponse succincte à certaines de vos questions. Veuillez garder à l'esprit que ce n'est pas strictement mon domaine de recherche, donc certaines de mes informations peuvent être obsolètes / incorrectes.
Il existe de nombreux outils spécialement conçus pour prouver formellement les propriétés de Java et de C ++.
Cependant, il me faut faire une petite digression: que signifie prouver l’exactitude d’un programme? Le vérificateur de types Java prouve une propriété formelle d'un programme Java, à savoir que certaines erreurs, telles que l'ajout d'un
float
et d'unint
, ne peuvent jamais se produire! J'imagine que vous êtes intéressé par des propriétés beaucoup plus fortes, à savoir que votre programme ne peut jamais entrer dans un état indésirable, ou que la sortie d'une certaine fonction est conforme à une certaine spécification mathématique. En bref, il existe un large gradient de ce que "prouver qu'un programme est correct" peut signifier, allant de simples propriétés de sécurité à une preuve complète que le programme remplit une spécification détaillée.Maintenant, je vais supposer que vous êtes intéressé par la démonstration de propriétés fortes de vos programmes. Si les propriétés de sécurité vous intéressent (votre programme ne peut pas atteindre un certain état), alors, en général, il semble que la meilleure approche est la vérification du modèle . Toutefois, si vous souhaitez spécifier pleinement le comportement d'un programme Java, le mieux est d'utiliser un langage de spécification pour ce langage, par exemple JML . Il existe de tels langages pour spécifier le comportement des programmes C, par exemple ACSL , mais je ne connais pas le C ++.
Une fois que vous avez vos spécifications, vous devez prouver que le programme est conforme à ces spécifications.
Pour cela, vous avez besoin d’un outil qui comprenne formellement votre spécification et la sémantique opérationnelle de votre langage (Java ou C ++) afin d’exprimer le théorème d’adéquation , à savoir que l’exécution du programme respecte la spécification.
Cet outil devrait également vous permettre de formuler ou de générer la preuve de ce théorème. Maintenant, ces deux tâches (spécifier et prouver) sont assez difficiles, elles sont donc souvent séparées en deux:
Un outil qui analyse le code, la spécification et génère le théorème d’adéquation. Comme Frank l'a mentionné, Krakatoa est un exemple d'un tel outil.
Un outil qui prouve le ou les théorèmes, automatiquement ou de manière interactive. Coq interagit avec Krakatoa de cette manière, et il existe de puissants outils automatisés tels que Z3 qui peuvent également être utilisés.
Un point (mineur): il existe des théorèmes qui sont beaucoup trop difficiles à prouver avec des méthodes automatisées, et les prouveurs automatiques de théorèmes ont parfois des bogues de correction qui les rendent moins dignes de confiance. C'est un domaine où Coq brille en comparaison (mais ce n'est pas automatique!).
Si vous voulez générer du code Ocaml, écrivez d'abord en Coq (Gallina), puis extrayez le code. Cependant, Coq est terrible pour générer du C ++ ou Java, si c'est même possible.
Les outils ci-dessus peuvent-ils gérer les problèmes de threading et de performance? Probablement pas, les problèmes de performances et de threading sont mieux gérés par des outils spécialement conçus, car ce sont des problèmes particulièrement difficiles. Je ne suis pas sûr d'avoir des outils à recommander ici, bien que le projet PolyNI de Martin Hofmann semble intéressant.
En conclusion: la vérification formelle des programmes Java et C ++ "réels" est un domaine vaste et bien développé, et Coq convient à certaines parties de cette tâche. Vous pouvez trouver un aperçu de haut niveau ici par exemple.
la source
Je voudrais mentionner trois applications remarquables de méthodes formelles / d’outils de vérification formels dans l’industrie ou de systèmes réels non triviaux. Notez que j'ai peu d'expérience sur ce sujet et que je ne les apprends qu'en lisant des articles.
L'outil open source Java Pathfinder (JPF, en abrégé) publié par la NASA en 2005 est un système permettant de vérifier les programmes de bytecode Java exécutables (voir Java Pathfinder @ wiki ). Il a été utilisé pour détecter des incohérences dans le logiciel exécutif du K9 Rover de la NASA Ames.
Ce document: Utilisation de la vérification de modèle pour rechercher des erreurs de système de fichiers graves @ OSDI'04 montre comment utiliser la vérification de modèle pour rechercher des erreurs graves dans les systèmes de fichiers. Un système appelé FiSC est appliqué à trois systèmes de fichiers largement utilisés et largement testés: ext3, JFS et ReiserFS, et 32 bogues sérieux sont détectés. Il a remporté le prix du meilleur article.
Ce document: Utilisation des méthodes formelles par Amazon Web Services @ CACM'15 décrit comment AWS applique des méthodes formelles à ses produits tels que S3, DynamoDB, EBS et le gestionnaire de verrous distribués internes. Il se concentre sur l' outil TLA + de Lamport . À propos, Lamport a utilisé de manière intensive sa propre boîte à outils TLA. Il donne souvent une vérification formelle (assez complète) dans TLA des algorithmes / théorèmes proposés par lui-même (ainsi que par les coauteurs) dans les annexes des articles.
la source
Une spécification formelle d'un programme est (plus ou moins) un programme écrit dans un autre langage de programmation. En conséquence, la spécification inclura certainement ses propres bogues.
L'avantage de la vérification formelle est que, comme le programme et la spécification sont deux implémentations distinctes, leurs bogues seront différents. Mais pas toujours: une source commune de bugs, les cas négligés, sera souvent identique. Ainsi, la vérification formelle n'est pas une panacée: il peut encore rater un nombre non négligeable de bugs.
Un inconvénient de la vérification formelle est qu’elle peut imposer deux fois le coût d’implémentation, probablement plus (vous avez besoin d’un spécialiste en spécification formelle, et vous devez utiliser les outils plus ou moins expérimentaux qui vont avec; cela ne va pas coûter cher ).
J'imagine que la configuration de cas de test et d'un échafaudage pour les exécuter automatiquement serait une meilleure utilisation de votre temps.
la source
La vérification formelle est désormais possible pour les programmes écrits dans un sous-ensemble de C ++ conçu pour les systèmes intégrés critiques pour la sécurité. Voir http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.ppt pour une brève présentation et http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.pdf pour le texte intégral.
la source
Vous posez quelques questions différentes. Je conviens qu'il semble que les méthodes de vérification formelle pour les applications industrielles / commerciales ne soient pas si courantes. il faut toutefois savoir que les compilateurs intègrent un grand nombre de principes de "vérification formelle" pour déterminer la correction du programme! En un sens, si vous utilisez un compilateur moderne, vous utilisez une grande partie de l'état de l'art en matière de vérification formelle.
Vous dites "j'en ai assez des tests" mais la vérification formelle ne remplace pas vraiment les tests. D'une certaine manière, c'est une variante des tests.
Vous parlez de Java. Il existe de nombreuses méthodes de vérification formelle avancées intégrées dans un programme de vérification Java appelé FindBugs qui peuvent en effet être exécutées sur de grandes bases de code. Notez que les résultats seront "faux positifs et faux négatifs" et que les résultats doivent être revus / analysés par un développeur humain. Mais notez que même s’il ne présente pas de défauts fonctionnels réels, il indique généralement des «antipatterns» qui doivent de toute façon être évités dans le code.
Vous ne faites plus mention de votre application particulière autre que "industrielle". La vérification formelle dans la pratique a tendance à dépendre de l'application particulière.
Les techniques de vérification formelle semblent être largement utilisées en EE pour prouver la correction des circuits, par exemple dans la conception de microprocesseurs.
Voici un exemple d'enquête sur les outils de vérification formels dans le domaine de l' efficacité énergétique réalisée par Lars Philipson .
la source
Peut-être qu'un vérificateur de modèle pourrait être utile.
http://alloytools.org/documentation.html Alloy est un vérificateur de modèles.
Une belle présentation expliquant le concept de vérification de modèle à l'aide d'Alloy: https://www.youtube.com/watch?v=FvNRlE4E9QQ
Dans la même famille d'outils, il y a les «tests basés sur les propriétés», ils essaient tous de trouver un contre-exemple pour le modèle de spécification donné de votre logiciel.
la source