Читает ли неопределенное значение неопределенное поведение? - PullRequest
11 голосов
/ 25 ноября 2010

Вопрос возник в комментариях к ответу на вопрос Всегда ли тип bool в C / C ++ всегда гарантированно равен 0 или 1, когда typecast'ed к int?

Данный код выделяет (локальный) массив bool без инициализации их значения.

const int n = 100;
bool b[n];

Очевидно, что значения в b являются неопределенными.

Некоторые комментаторы высказали мнение, что чтение, например, b[0] было неопределенным поведением. Это указано где-нибудь в стандарте C ++? Я все еще убежден в обратном:

  1. Явно выделено хранилище, и инициализация основного типа bool завершена, поскольку у него нет конструктора. Таким образом, это, конечно, не то же самое, что разыменование неинициализированного указателя или вызов методов / операторов приведения к неинициализированным нетривиальным объектам. Эти конкретные случаи, кажется, охватываются стандартом.

  2. Поведение действительно не определено в C:

Что происходит с объявленной неинициализированной переменной в C? Имеет ли оно значение? , и некоторые респонденты, кажется, путают их.

В последней версии C ++ 0x я не могу найти определения неопределенного значения , особенно определения, которое позволило бы получить доступ к такому значению, чтобы вызвать прерывание процессора. В действительности, Бьярн Страуструп не уверен, каким может быть внутреннее значение: http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

Ответы [ 4 ]

6 голосов
/ 02 мая 2014

Ответ на этот вопрос меняется с последним рабочим проектом C ++ 1y (N3946), который мы можем найти здесь .Раздел 8.5 Инициализаторы абзац 12 сильно отличается от C ++ 03 и C ++ 11 и теперь содержит следующее ( выделение мое ):

Если для объекта не указан инициализатор, объект инициализируется по умолчанию. Когда получено хранилище для объекта с автоматической или динамической продолжительностью хранения, объект имеет неопределенное значение , и если для объекта не выполняется инициализация, этот объект сохраняет неопределенное значение доэто значение заменяется (5.17).[Примечание: объекты со статическим или потоковым хранением инициализируются нулями, см. 3.6.2.- примечание к концу] Если в результате оценки получено неопределенное значение, поведение не определено, за исключением следующих случаев :

и далее перечисляются некоторые исключения для узкий символьный тип без знака , у меня есть полная цитата в Изменился ли C ++ 1y в отношении использования неопределенных значений и неопределенного поведения? .

Так в вашем случаеb имеет автоматическую продолжительность хранения и не инициализируется, и поэтому имеет неопределенное значение.Таким образом, оценка b[0] действительно неопределенное поведение.

Ранее нам требовалось использовать преобразование lvalue-to-rvalue, чтобы доказать, что оно не определено, но это проблематично, поскольку преобразование недоопределено .

Обратите внимание, что неопределенное значениевыделен курсивом в этом разделе, и, следовательно, это означает, что он определен на месте, и теперь C ++ 1y фактически определяет этот термин.Ранее термин использовался без определения, это описано в отчете о дефектах 616 .

4 голосов
/ 25 ноября 2010

На bool, стандарт гласит в 3.9.1 Основные типы :

Значения типа bool являются либо истинными, либо ложными.

со сноской, в которой указано:

Использование значения bool способами, описанными в настоящем международном стандарте как «неопределенный» , например, путем проверки значения неинициализированного автоматического объектаможет заставить его вести себя , как если бы он не был ни истинным, ни ложным.

4 голосов
/ 25 ноября 2010

Да, формально преобразование в Rvalue неопределенного значения - это UB (за исключением unsigned char, изначально я писал «и варианты», но, как я помню, формально обслуживает дополненный символ 1 со знаком, где возможно использование минус 0 в качестве значения ловушки )

я слишком ленив, чтобы сделать стандартный поиск абзаца для вас, а также ленивый, чтобы заботиться о снижении голосов за это

однако на практике проблема только в (1) архаичных архитектурах и, возможно, (2) 64-битных системах.

РЕДАКТИРОВАТЬ : упс, теперь мне кажется, что я вспоминаю публикацию в блоге и связанный отчет о дефектах о формальном UB для доступа к неопределенному символу. так что, возможно, мне придется на самом деле проверить стандарт, + поиск DR. аааа, это будет потом потом, теперь кофе!

EDIT2 : Йоханнес Шауб любезно предоставил эту ссылку на вопрос SO , где обсуждался UB для доступа к char. Так вот откуда я это запомнил! Спасибо, Йоханнес.

ура и hth.,

0 голосов
/ 07 мая 2016

Тот факт, что чтение неопределенного значения обычно приводит к неопределенному поведению, является не просто «теоретической» проблемой.Даже для типов, в которых все возможные битовые комбинации имеют определенные значения, не следует считать «удивительным», что неопределенные значения ведут себя так, как отличаются от неуказанных значений.Например, если * p содержит неопределенное значение, а x нигде не используется, кроме как показано, код:

uint32_t x,y,z;
...
x = *p;
if (condition1) y=x;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=x;

можно переписать как:

if (condition1) y=*p;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=*p;

Если значение* p является Indeterminate, компилятору не будет запрещено иметь код между двумя операторами «if», изменяющими его значение.Например, если память, занятая * p, была занята "float" до его освобождения и повторного malloc'а, компилятор может записать это значение "float" между двумя операторами "if" выше.

...