Indéfini, indéterminé et de mise en œuvre définies par le comportement
Ce qui est un comportement indéfini dans le C et le C++? Ce sujet quelconque comportement et la mise en œuvre définies par le comportement? Quelle est la différence entre eux?
- Je suis presque sûr que nous avons dne cela avant, mais je ne le trouve pas. Voir aussi: stackoverflow.com/questions/2301372/...
- À partir de la comp.lang.c FAQ: les Gens semblent faire un point de la distinction entre la mise en œuvre définies, non spécifié, et un comportement indéfini. Que veulent-ils dire?
- theunixshell.blogspot.com/2013/07/...
- Voici une discussion intéressante (la section "Annexe L, et un Comportement non défini").
Vous devez vous connecter pour publier un commentaire.
Comportement indéfini est l'un de ces aspects de la C et C++ un langage qui peut être surprenant pour les programmeurs venant d'autres langues (autres langues essayer de le cacher mieux). Fondamentalement, il est possible d'écrire des programmes C++ qui ne se comportent pas de façon prévisible, même si de nombreux compilateurs C++ ne pas signaler toute erreur dans le programme!
Regardons un exemple classique:
La variable
p
points de la chaîne de caractères littérale"hello!\n"
, et les deux affectations ci-dessous tentent de modifier cette chaîne littérale. Ce que fait ce programme? Conformément à l'article 2.14.5 paragraphe 11 de la norme C++, il appelle comportement indéfini:J'entends des gens crier "Mais attendez, je peux compiler ce pas de problème et obtenir la sortie
yellow
" ou "Qu'entendez-vous pas défini, les littéraux de chaîne sont stockées dans la mémoire en lecture seule, donc, la première affectation tentative résultats dans un core dump". C'est exactement le problème avec un comportement indéfini. En gros, la norme permet à autre chose une fois que vous invoquez un comportement indéfini (même nasale démons). Si il y a une "bonne" comportement en fonction de votre modèle mental de la langue, ce modèle est tout simplement faux; La norme C++ est le seul vote, période.D'autres exemples de comportement indéfini comprennent l'accès à un tableau au-delà de ses limites, un déréférencement du pointeur null, l'accès à des objets d'après leur durée de vie terminée ou de l'écriture prétendument intelligents expressions comme
i++ + ++i
.L'article 1.9 du C++ standard mentionne également un comportement indéfini deux moins dangereux frères, comportement non spécifié et de mise en œuvre définies par le comportement:
Plus précisément, l'article 1.3.24 états:
Que pouvez-vous faire pour éviter de courir dans un comportement indéfini? En fait, vous devez lire bon C++ livres par les auteurs, qui savent de quoi ils parlent. À vis de l'internet des tutoriels. Vis bullschildt.
int f(){int a; return a;}
: la valeur dea
peuvent changer entre les appels de fonction.auto q= "hello!\n";
q maintenant, peut ou ne peut pas être "bonjour!\n" ou "jaune\n" et pour le pire; q peut ou peut ne pas être dans la même fonction que p.Bien, c'est essentiellement un droit de copier-coller à partir de la norme
a[i] = i++
est pas défini. Est-il possible pour un compilateur pour être suffisamment sophistiqué pour être programmé pour cet événement? Qu'arriverait-il, il serait juste de sortie aléatoire de l'assemblée?int foo(int x) { if (x >= 0) launch_missiles(); return x << 1; }
un compilateur peut déterminer que, puisque tous les moyens d'invoquer la fonction ne pas lancer les missiles invoquer un Comportement Indéfini, il peut faire appel àlaunch_missiles()
inconditionnel.Peut-être facile libellé pourrait être plus facile de comprendre que la rigueur de définition des normes.
de mise en œuvre définies par le comportement
La langue dit que nous avons des types de données. Le compilateur vendeurs de spécifier quelles sont les tailles sont qu'ils utilisent, et de fournir une documentation de ce qu'ils ont fait.
comportement indéfini
Vous faites quelque chose de mal. Par exemple, vous avez une très grande valeur dans un
int
qui ne rentre pas danschar
. Comment voulez-vous mettre cette valeur danschar
? en fait il n'y a pas de chemin! Quelque chose pourrait se produire, mais la chose la plus sensée serait de prendre le premier octet de l'int et de mettre enchar
. Il est tout simplement erroné de le faire pour attribuer le premier octet, mais c'est ce qui se passe sous le capot.comportement non spécifié
La fonction de ces deux est exécuté en premier?
La langue n'a pas spécifier l'évaluation, de gauche à droite ou de droite à gauche! Si un quelconque problème peut ou mayn pas donner lieu à un comportement indéfini, mais certainement votre programme ne doit pas produire un comportement quelconque.
@eskay aux je pense que ta question vaut la peine d'édition de la réponse à clarifier les plus 🙂
La différence entre la mise en œuvre définies et non précisées, c'est que le compilateur est censé choisir un comportement dans le premier cas, mais ce ne sont pas que dans le second cas. Par exemple, une mise en œuvre doit avoir une et une seule définition de
sizeof(int)
. Donc, il ne peut pas dire quesizeof(int)
est 4 pour une partie du programme et de 8 pour les autres. À la différence de comportement quelconque, où le compilateur peut dire OK, je vais évaluer ces arguments de gauche à droite et du côté de la fonction, les arguments sont évalués de droite à gauche. Il peut arriver dans le même programme, c'est pourquoi il est appelé non spécifié. En fait, C++ aurait été plus facile si certains de l'une quelconque des comportements ont été spécifiés. Jetez un coup d'oeil ici à Le dr de Stroustrup réponse pour que:fun(fun1(), fun2());
n'est pas le comportement"implementation defined"
? Le compilateur doit choisir l'un ou l'autre, après tout?"I am gonna evaluate these arguments left-to-right and the next function's arguments are evaluated right-to-left"
je comprends cecan
arriver. Est-il vraiment, avec les compilateurs que nous utilisons de nos jours?De l'officiel C Justification Document
Un Comportement indéfini vs Comportement non spécifié a une courte description de celui-ci.
Leur finale résumé:
Point de vue historique, la mise en Œuvre Définies par le Comportement et Comportement Indéfini correspondent à des situations dans lesquelles les auteurs de la Norme attend à ce que les gens de l'écriture de la qualité des implémentations ferait usage de jugement pour décider du comportement des garanties, le cas échéant, serait utile pour des programmes dans le domaine d'application en cours d'exécution sur les cibles. Les besoins de haut de gamme arithmétique code sont très différentes de celles de faible niveau des systèmes de code, et à la fois AC et de la BID donner les rédacteurs du compilateur de flexibilité pour répondre à ces différents besoins. Ni la catégorie des mandats que les implémentations de se comporter d'une manière qui est utile pour un usage particulier, ou même pour n'importe quel but que ce soit. La qualité des implémentations qui demande à être adapté pour un usage particulier, cependant, doit se comporter d'une manière digne de cette fin si la Norme l'exige ou pas.
La seule différence entre la mise en Œuvre Définies par le Comportement et Comportement Indéfini, c'est que le premier exige que les implémentations de définir et de documenter un comportement cohérent même dans les cas où rien de la mise en œuvre pourrait, éventuellement, ne serait utile. La ligne de démarcation entre eux n'est pas de savoir si il serait généralement utile pour les implémentations de définir les comportements (les rédacteurs du compilateur doit définir utile comportements lors de la pratique si la Norme exige d'eux ou pas) mais s'il pourrait y avoir des implémentations d'où la définition d'un comportement serait d'être à la fois coûteux et inutile. Un jugement que ces implémentations peuvent exister n'est pas en aucune manière, la forme, ou la forme, implique aucun jugement sur l'utilité de soutenir un comportement défini sur d'autres plates-formes.
Malheureusement, depuis le milieu des années 1990, les rédacteurs du compilateur ont commencé à interpréter l'absence de comportement des mandats d'arrêt qui comportementale garanties ne sont pas en vaut le coût, même dans les champs d'application où elle est vitale, et même sur les systèmes où ils coûtent pratiquement rien. Au lieu de traitement de l'UB, comme une invitation à faire preuve de jugement, le compilateur les écrivains ont commencé à la traiter comme une excuse pas de le faire.
Par exemple, le code suivant:
un complément à deux sur la mise en œuvre n'aurait pas à dépenser le moindre effort
que ce soit pour traiter l'expression
v << pow
comme un complément à deux majsans égard pour savoir si
v
était positif ou négatif.Privilégiées de philosophie de la part de certains aujourd'hui, les rédacteurs du compilateur, cependant, suggère que parce que
v
ne peut être que négative si le programme va s'engager dans un Comportement Indéfini, il n'y a pas de raison d'avoir le programme le clip de la plage négative dev
. Même si la gauche déplacement des valeurs négatives utilisé pour être pris en charge sur chaque compilateur de signification, et une grande quantité de code existant repose sur le comportement, la philosophie moderne interpréter le fait que la Norme dit que la gauche décalage des valeurs négatives UB comme impliquant que les rédacteurs du compilateur doit se sentir libre d'en tenir compte.<<
UB sur les nombres négatifs est un vilain petit piège et je suis heureux de le rappeler!i+j>k
rendements 1 ou 0 dans le cas où l'ajout des débordements, à condition qu'il n'a pas d'autres effets secondaires, un compilateur peut être en mesure de faire quelques massive des optimisations qui ne serait pas possible si le programmeur a écrit le code que(int)((unsigned)i+j) > k
.De mise en œuvre définies
Non spécifié -
Undefined-
uint32_t s;
, l'évaluation de1u<<s
quands
est de 33 pourrait peut-être le rendement de 0 ou peut-être de rendement 2, mais ne pas faire quelque chose de loufoque. Nouveaux compilateurs, cependant, l'évaluation de1u<<s
peut provoquer un compilateur de déterminer que, parce ques
doit avoir moins de 32 à l'avance, tout le code avant ou après cette expression qui ne serait pertinent que sis
a été de 32 ou plus peut être omis.C++ standard n3337 § 1.3.10
de mise en œuvre définies par le comportement
Parfois C++ Standard n'impose pas de comportement particulier sur certaines constructions, mais dit plutôt qu'un particulier, comportement bien déterminé doit être choisi et décrit en particulier la mise en œuvre (version de bibliothèque). De sorte que l'utilisateur peut toujours savoir exactement comment sera le programme se comporter, même si la Norme n'est pas de décrire cette.
C++ standard n3337 § 1.3.24
comportement indéfini
Lorsque le programme rencontre de construire qui n'est pas définie selon la Norme C++, il est autorisé de faire ce qu'il veut faire ( peut-être envoyer un e-mail à moi-même ou peut-être envoyer un e-mail pour vous ou peut-être ignorer le code complètement).
C++ standard n3337 § 1.3.25
comportement non spécifié
C++ Standard n'impose pas de comportement particulier sur certaines constructions, mais dit plutôt qu'un particulier, comportement bien déterminé doit être choisi ( bot n'est pas nécessaire décrite) en particulier la mise en œuvre (version de bibliothèque). Donc, dans le cas où aucune description n'a été fourni, il peut être difficile pour l'utilisateur de savoir exactement comment sera le programme se comporter.