11
votes

La lecture d'une valeur indéterminée est-elle un comportement indéfini?

La question se poser dans les commentaires d'une réponse à la question est C / C ++ Bool Tyol toujours garanti d'être 0 ou 1 lorsque Typecast'ed to int?

Le code en question attribue une (local) Array de BOOL sans initialiser leur valeur. xxx

clairement les valeurs dans B sont indéterminés.

Certains des commentateurs ont opté que la lecture par exemple. b [0] était un comportement indéfini. Est-ce indiqué n'importe où dans la norme C ++? Je suis toujours convaincu du contraire:

  1. Il existe clairement le stockage alloué et l'initialisation du type de bool fondamental est terminée, car elle n'a pas de constructeur. Ce n'est donc certainement pas la même chose que la déséroférance d'un pointeur ininitialisé ou d'appeler des méthodes / des opérateurs de distribution sur des objets non triviaux non incialisés. Ces cas spécifiques semblent être couverts par la norme.

  2. Le comportement est en effet non défini dans C: Qu'advient-il de la variable déclarée et non initialisée en C? At-il une valeur? et certains répondants semblent confondre les deux.

  3. Dans le dernier brouillon C ++ 0X, je ne trouve aucune définition de valeur indéterminée notamment sans définition qui permettrait d'accéder à une telle valeur de déclencher un piège à processeur. En effet, Bjarne Stroustrup n'est pas sûre de savoir quelle valeur indermine peut être: http: //zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html


5 commentaires

Oh bien, "comportement indéfini" est un terme très favori ici dans Stackoverflow et il est utilisé pour tout, de la mise en œuvre définie, par non spécifié jusqu'à la réelle non définie.


Je veux dire que les "démons nasaux" proverbial sont indéfinis.


Et btw. 8.5 - 9 parle de cela.


@Let_me_be: Cela peut être vrai et parfois, les gens pourraient parfois classer accidentellement certains cas, même s'ils comprennent la différence. Mais ceci est UB dans le seul sens qui compte, quel est le sens défini dans la norme.


Remarque, ma réponse à est ininitialisée variable locale le générateur de nombres aléatoires le plus rapide? est également pertinent et nous pouvons voir que les compilateurs sont activement tirer parti du comportement indéfini autour des valeurs indéterminées.


4 Réponses :


6
votes

Oui, formellement une conversion de rvalue de valeur indéterminée est UB (à l'exception de sans signé Char , à l'origine, j'ai écrit "et des variantes", mais comme je me souviens de l'accélérateur formel sur 1 complément de 1 pourrait être utilisé comme valeur de piège)

Je suis trop paresseux pour faire la recherche de paragraphe standard pour vous et aussi paresseux de vous soucier des bowvotes pour que

Cependant, dans la pratique, seul un problème sur (1) architectures archaïques, et peut-être (2) systèmes 64 bits.

EDIT : Oups, je semble maintenant rappeler un rapport d'affichage du blog et de défaut associé sur la Formelle UB pour accéder à un caractère indéterminé. Donc, peut-être que je devrai réellement vérifier la norme, + la recherche. Argh, ce devra être plus tard alors, maintenant café!

Edit2 : Johannes Schaub a eu la gentillesse de fournir à ce Lien vers cette question où cette UB pour accéder à l'argent a été discutée. Alors, c'est là que je me suis souvenu de ça! Merci Johannes.

acclamations et hth.,


8 commentaires

@downvoter: Veuillez indiquer la raison de la Downvote afin que d'autres puissent apprendre ce qui ne va pas dans une réponse, ou pourquoi votre bowvote est stupide.


+1. 4.1 / 1: "Un lvalue (3.10) d'une non-fonction, type Type T-réseau t peut être converti en une rvalue. Si T est un type incomplet, un programme qui nécessite cette conversion est mal formé. Si l'objet à Lequel le lvalue fait référence n'est pas un objet de type T et n'est pas un objet d'un type dérivé de T, ou si l'objet est ininitialisé, un programme qui nécessite cette conversion a un comportement indéfini. "


Hey, je ne vous ai pas descendu pour votre paresseux. Cependant, je ne pouvais peut-être pas non plus.


Merci, j'avais trouvé le paragraphe pertinent [CONV.LVAL] dans le dernier FCD. Cependant, BOOL & BR = B [0] n'est pas une prvalue mais un glvalue si je ne me trompe pas. Le problème est alors que tout ce que je fais à br (à l'exception de l'affectation) nécessite la conversion sur une rvalue, non?


Et votre lien pointe vers YouTube.com, pas une question si question. Amusez-vous certainement, mais peut-être pas ce que vous alliez faire :-)


@Sebastian: corrigé, je pense! :-) Merci!


@Sebastian: Désolé, je ne peux pas vous aider avec C ++ 0x, je ne comprends pas encore ces types de valeur supplémentaires. Je parle seulement de la norme. Il semble peu probable que cela soit délibérément transformé en c ++ 0x, cependant, car le seul comportement défini que je puisse penser est de dire que le bool a une valeur (vraie ou faux), mais il n'est pas spécifié lequel. En pratique, cela signifie masquer chaque fois qu'une valeur de bool est lue du stockage plus grand, sans avantage.


Intéressant même que la résolution proposée dans le Dr Lié par Johannes n'a pas été mise en œuvre dans le FCD (ou N3126).



5
votes

sur bool , la norme dit sous 3,9.1 Types fondamentaux :

Les valeurs de type bool sont soit vraie, soit faux.

avec une note de bas de page indiquant:

Utilisation d'une valeur BOOL de manière décrite par cette norme internationale comme "non défini", comme en examinant le valeur d'un automatique inaitalisé objet, pourrait causer son comportement comme si Ce n'est ni vrai ni faux.


0 commentaires

6
votes

La réponse à cette question change avec le dernier brouillon de travail C ++ 1y ( N3946 ) que nous pouvons trouver ICI . Section 8.5 initialiseurs paragraphe 12 change beaucoup de C ++ 03 et C ++ 11 et contient maintenant les éléments suivants ( emphasis. ):

Si aucun initialiseur n'est spécifié pour un objet, l'objet est Initialisée par défaut. lorsque vous stockez un objet avec automatique ou La durée de stockage dynamique est obtenue, l'objet a un indéterminé valeur , et si aucune initialisation n'est effectuée pour l'objet, que L'objet conserve une valeur indéterminée jusqu'à ce que cette valeur soit remplacée. (5.17). [Remarque: les objets avec la durée statique ou de stockage de thread sont Zero-initialisé, voir 3.6.2. - Note de fin] si une valeur indéterminée est Produit par une évaluation, le comportement n'est indéfini sauf dans la Suivre les cas :

et continue à énumérer des exceptions à des exceptions pour Type de caractère étroit non signé seulement, j'ai une citation complète dans a C ++ 1y modifié par rapport à l'utilisation de valeurs indéterminées et de comportement non défini? .

Donc, dans votre cas, B a une durée de stockage automatique et n'est pas initialisé et a donc une valeur indéterminée. Ainsi, évaluer b [0] est en effet un comportement non défini.

Auparavant, nous devions utiliser la conversion de LValue-to-RValue pour prouver que cela était indéfini mais qui est problématique depuis La conversion est sous-spécifiée .

Notez que la valeur indéterminée est en italique dans cette section et cela signifie donc qu'il est en train de définir en place et donc maintenant C ++ 1y définit réellement le terme. Auparavant, le terme a été utilisé sans définition, ceci est couvert dans Rapport de défaut 616 .


0 commentaires

0
votes

Le fait que la lecture d'une valeur indéterminée entraîne généralement un comportement non défini n'est pas simplement un problème «théorique». Même pour les types où tous les modèles de bits possibles ont défini des valeurs, il ne doit pas être considéré comme "surprenant" pour des valeurs indéterminées de se comporter de manière différente des valeurs non spécifiées. Par exemple, si * P contient la valeur indéterminée, et x n'est utilisé nulle part sauf Comme indiqué, le code: xxx

pourrait être réécrit comme suit: xxx

si la valeur de * p est indéterminée, un compilateur ne serait pas être interdit d'avoir le code entre les deux déclarations "si" modifier sa valeur. Par exemple, si le stockage occupé par * P était occupé par un "flotteur" Avant de libérer et de re-malloc'ed, le compilateur peut écrire ce "flotteur" valeur entre les deux "si" déclarations ci-dessus.


0 commentaires