72 votes

Une implémentation C++ qui détecte un comportement indéfini?

Un grand nombre d'opérations en C++ entraîner un comportement non défini, où la spec est complètement muet sur ce que le programme du comportement doivent être et permet à tout pour arriver. De ce fait, il y a toutes sortes de cas où les gens ont un code qui compile en debug mais pas en mode release, ou qui fonctionne jusqu'à un apparemment sans rapport avec le changement est fait, ou qui travaille sur une machine mais pas sur un autre, etc.

Ma question est de savoir si il existe un utilitaire qui ressemble à l'exécution de code C++ et les drapeaux de tous les cas où le programme invoque un comportement indéfini. Alors que c'est bien que nous avons des outils comme valgrind et vérifié STL implémentations, ce n'est pas aussi forte que ce que je suis en train de réfléchir - valgrind peut avoir des faux négatifs si vous corbeille de mémoire que vous avez encore allouées, par exemple, et vérifié STL implémentations ne prends pas de supprimer au moyen d'une base de pointeur de classe.

Cet outil existe pas? Ou serait-il même être utile de l'avoir qui traînent à tous?

EDIT: je suis conscient qu'il est en général indécidable statiquement vérifier si un programme C++ peut jamais exécuter quelque chose qui a un comportement indéfini. Toutefois, il est possible de déterminer si une exécution spécifique en C++ produit un comportement indéfini. Une façon de le faire serait de faire une C++ interprète qui suit dans le code selon les définitions figurant dans la spécification, à chaque point de déterminer si oui ou non le code a un comportement indéfini. Ce ne sera pas en mesure de détecter un comportement indéfini qui ne se produit pas sur un programme particulier d'exécution, mais il va trouver tout un comportement indéfini qui en réalité se manifeste dans le programme. Ceci est lié à la façon dont il est Turing-reconnaissable pour déterminer si un TM accepte une entrée, même si ça reste indécidable en général.

Merci!

23voto

Nemo Points 32838

C'est une grande question, mais permettez-moi de vous donner une idée de pourquoi je pense qu'il pourrait être impossible (ou du moins très difficile) en général.

Sans doute, une telle mise en œuvre serait presque un C++ interprète, ou au moins un compilateur pour quelque chose de plus comme Lisp ou Java. Il faudrait garder des données supplémentaires pour chaque pointeur pour vous assurer de ne pas effectuer de l'arithmétique à l'extérieur d'un tableau ou de déréférencement de quelque chose qui a déjà été libéré ou que ce soit.

Maintenant, considérons le code suivant:

int *p = new int;
delete p;
int *q = new int;

if (p == q)
    *p = 17;

Est l' *p = 17 comportement indéfini? D'une part, il déréférence p après qu'il a été libérée. D'autre part, de déférence q est fine et p == q...

Mais ce n'est pas vraiment le point. Le point est que si l' if s'évalue à vrai au tout dépend des détails de la masse, de la mise en œuvre, qui peut varier de mise en œuvre de la mise en œuvre. Pour le remplacer *p = 17 par un comportement indéfini, et que vous avez un programme qui peut très bien sauter sur un compilateur normal, mais de l'exécuter correctement sur votre hypothétique "UB détecteur". (Typique de l'implémentation C++ va utiliser un PRINCIPE de libre liste, de sorte que les pointeurs ont une bonne chance d'être égaux. Une hypothétique "UB détecteur" pourrait fonctionner plus comme un de ces ordures de la langue afin de détecter les use-after-free de problèmes.)

Mettre une autre manière, l'existence de la simple mise en œuvre définies comportement rend impossible d'écrire un "UB détecteur" qui fonctionne pour tous les programmes, je le soupçonne.

Cela dit, un projet de création d'un "uber-strict compilateur C++" ce serait très intéressant. Laissez-moi savoir si vous voulez démarrer une. :-)

21voto

Shafik Yaghmour Points 42198

Jean Regehr en Trouver un Comportement Indéfini de Bugs par recherche de Code Mort de points d'un outil appelé PILE et je cite le site (c'est moi qui souligne):

Optimisation instable code (instable code pour faire court) est une classe émergente de bugs logiciels: le code qui est, de façon inattendue éliminé par les optimisations du compilateur en raison d'un comportement non défini dans le programme. Instable code est présent dans de nombreux systèmes, y compris le noyau Linux et le Postgresql base de données du serveur. Les conséquences de l'instabilité de la portée du code de la mauvaise fonctionnalité du manque de contrôles de sécurité.

La PILE est une vérification statique qui détecte instable code dans les programmes C/C++ . L'application PILE à largement recours à des systèmes a permis de découvrir de 160 nouveaux bugs qui ont été confirmés et corrigé par les développeurs.

Aussi en C++11 pour le cas de constexpr des variables et des fonctions de comportement indéfini doit être pris au moment de la compilation.

Nous avons également gcc ubsan:

GCC récemment (version 4.9) a gagné un Comportement Indéfini Désinfectant (ubsan), un vérificateur pour les langages C et C++. Afin de vérifiez votre programme avec ubsan, de compiler et lier le programme avec -fsanitize=undefined option. Ces binaires instrumentés être exécuté; si ubsan détecte un problème, il affiche une "erreur d'exécution:" message, et dans la plupart des cas, continue l'exécution du programme.

et Clang Analyseur Statique qui comprend de nombreux contrôles pour un comportement indéfini. Par exemple clangs -fsanitize contrôles qui inclut -fsanitize=undefined:

-fsanitize=undefined: Rapide et compatible un comportement indéfini checker. Permet le comportement non défini vérifications qui ont des petits exécution de coût et de aucun impact sur le format d'espace d'adresse ou d'ABI. Cela comprend toutes les contrôles énumérés ci-dessous d'autres que non signé entier-débordement.

et pour le C on peut regarder son article , Il est Temps de devenir Sérieux au Sujet de l'Exploitation de Comportement Indéfini qui dit:

[..]J'avoue ne pas avoir personnellement le bon sens nécessaire pour bachotage GCC ou LLVM par le biais de la meilleure dynamique de comportement indéfini pions: KCC et de Frama-C.[...]

Voici un lien vers kcc et je cite:

[...]Si vous essayez d'exécuter un programme qui n'est pas défini (ou celui pour lequel il nous manque de sémantique), le programme sera coincé. Le message devrait vous dire où il est resté coincé et ne peut donner un indice quant à pourquoi. Si vous voulez aider à déchiffrer la sortie, ou l'aide à comprendre pourquoi le programme n'est pas défini, veuillez envoyer votre .kdump fichier.[...]

et voici un lien vers Frama-C, un article où la première utilisation de Frama-C comme C interprète est décrite et un addendum à l'article.

13voto

dmckee Points 50318

À l'aide de g++

-Wall -Werror -pedantic-error

(de préférence avec un -std argument) va ramasser assez peu de cas de l'U. B.


Choses que -Wall vous permet de vous inclure:

-pédant
Problème de tous les avertissements requis par de strictes ISO C et ISO C++; rejeter tous les programmes de l'utilisation interdite des extensions, et quelques autres programmes qui ne suivent pas la norme ISO C et ISO C++. Pour l'ISO C, suit le la version de la norme ISO C standard spécifiées par toute option-std utilisé.

-Winit-auto (C, C++, Objective-C et Objective-C++ seulement)
Avertir sur les variables non initialisées qui sont initialisés avec les eux-mêmes. Remarque: cette option peut être utilisée uniquement avec le -Wuninitialized option, qui à son tour ne fonctionne qu'avec -O1 et ci-dessus.

-Wuninitialized
Avertir si une variable automatique est utilisé, sans être d'abord initialisé ou si une variable peut être touchée par un "setjmp" appel.

et divers interdits choses que vous pouvez faire avec les spécificateurs d' printf et scanf les fonctions de la famille.

13voto

Richard Smith Points 3935

Clang est une suite de désinfectants que les prises, les diverses formes de comportement indéfini. Leur objectif final est d'être capable d'attraper tous les C++ langage de base un comportement indéfini, mais vérifie un peu difficile formes de comportement indéfini sont manquantes à la droite maintenant.

Pour un bon set de désinfectants, essayez:

clang++ -fsanitize=undefined,address

-fsanitize=address des contrôles pour l'utilisation de mauvais pointeurs (ne pointe pas vers la mémoire valide), et -fsanitize=undefined permet à un ensemble de léger UB contrôles (dépassement d'entier, de mauvais quarts de travail, mal alignées pointeurs, ...).

-fsanitize=memory (pour la détection de la mémoire non initialisée lit) et -fsanitize=thread (pour détecter des données de courses) sont également utiles, mais qui ne peut être combiné avec d' -fsanitize=address ni les uns avec les autres parce que tous les trois ont une envahissantes incidence sur le programme de l'espace d'adressage.

5voto

Matthieu M. Points 101624

Vous voudrez peut-être lire sur SAFECode.

C'est un projet de recherche de l'Université de l'Illinois, le but qui est indiqué sur la page d'accueil (lien ci-dessus):

Le but de la SAFECode projet est de permettre au programme de sécurité sans la collecte des ordures et avec un minimum d'exécution vérifie à l'aide de l'analyse statique, si possible, et au moment de l'exécution vérifie si nécessaire. SAFECode définit une représentation de code avec un minimum de restrictions sémantiques conçu pour permettre statique de l'application de la sécurité, de l'aide agressif compilateur techniques développées dans ce projet.

Ce qui est vraiment intéressant pour moi, c'est l'élimination de l'exécution des contrôles à chaque fois que le programme peut être s'est avéré être correct statiquement, par exemple:

int array[N];
for (i = 0; i != N; ++i) { array[i] = 0; }

Ne devrait pas engager plus de ressources que la version régulière.

Dans un briquet de la mode, Clang a quelques garanties quant à un comportement indéfini trop autant que je me souvienne, mais je ne peux pas obtenir mes mains sur elle...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X