Требуется ли, чтобы неопределенное и неопределенное поведение было согласованным между компиляциями одной и той же программы с одним и тем же компилятором в одной среде? - PullRequest
0 голосов
/ 17 июня 2010

Давайте представим, что моя программа содержит определенную конструкцию, в которой стандартные состояния C ++ имеют неопределенное поведение.Это в основном означает, что реализация должна делать что-то разумное, но разрешено не документировать это.Но требуется ли реализация для создания одного и того же поведения каждый раз, когда она компилирует конкретную конструкцию с неопределенным поведением, или ей разрешено создавать различное поведение в разных компиляциях?

Как насчет неопределенного поведения?Давайте представим, что моя программа содержит конструкцию UB в соответствии со Стандартом.Реализация позволяет демонстрировать любое поведение.Но может ли это поведение отличаться между компиляциями одной и той же программы на одном и том же компиляторе с одинаковыми настройками в одной среде?Другими словами, если я разыменую нулевой указатель на строке 78 в файле X.cpp и реализация отформатирует диск в таком случае, значит ли это, что он будет делать то же самое после перекомпиляции программы?

Вопросэто ... Я компилирую ту же программу с тем же компилятором в той же среде с теми же настройками компилятора.Будет ли конструкция, заявленная как неопределенное поведение и неопределенное поведение, вызывать одинаковое поведение в каждой компиляции или им разрешено различаться в разных компиляциях?

Ответы [ 9 ]

5 голосов
/ 17 июня 2010

Если это неопределенное поведение, то по самой своей природе то, что произойдет, не определено, вы не можете полагаться на то, что оно будет таким же при при любых обстоятельствах.

Неуказанное поведение с другойhand - это что-то, что оставляют на усмотрение отдельных поставщиков решения о том, как их реализовать, например, если в спецификации языка есть неоднозначности.Это будет согласовано между компиляцией и запуском, но не обязательно между разными поставщиками.Так, например, полагаться на неопределенное поведение при сборке только с использованием Visual Studio - это нормально, но если вы попытаетесь перенести код на gcc, он может дать сбой или вызвать поведение, отличное от ожидаемого.

3 голосов
/ 17 июня 2010

Неуказанное и неопределенное поведение не гарантируется согласованностью между отдельными запусками уже скомпилированной программы.Уже одно это делает понятие согласованности между отдельными компиляциями совершенно бессмысленным.

Кроме того, вероятно, стоит добавить, что неопределенное поведение может проявляться на этапе компиляции, вообще предотвращая компиляцию программы.

3 голосов
/ 17 июня 2010

Неопределенное поведение может варьироваться между запусками одной и той же программы и даже между запуском одного и того же кода при одном и том же запуске программы.Например, значение неинициализированной (автоматической) переменной не определено, а затем ее фактическое значение равно значению, которое оказалось в этом месте в памяти.Очевидно, что это может варьироваться.

РЕДАКТИРОВАТЬ:

Это относится и к неопределенное поведение тоже.Например, порядок оценки аргументов функции не определен, поэтому, если они имеют побочные эффекты, эти побочные эффекты могут возникать в любом порядке.Это может напечатать "Привет! Хо!"или «Хо! Привет!»:

f( printf("Hi!"), printf("Ho!") );

Это также зависит от исполнения.Как гласит стандарт: «Таким образом, экземпляр абстрактной машины может иметь более одной возможной последовательности выполнения для данной программы и заданного ввода».Разница в том, что с поведением undefined может произойти все что угодно: компьютер может взорваться, переформатировать диск или что-то еще.Если поведение не указано, компьютеру запрещается взрываться.

Существует также поведение , определяемое реализацией *1015*, например значение sizeof(int).Это должно быть всегда одинаково для одного и того же компилятора.

2 голосов
/ 17 июня 2010

Но может ли это поведение отличаться между компиляциями одной и той же программы на одном и том же компиляторе с одинаковыми настройками в одной среде?

Да.

Вдругими словами, если я разыменую нулевой указатель на строке 78 в файле X.cpp и реализация отформатирует диск в таком случае, значит ли это, что он будет делать то же самое после перекомпиляции программы?

Результаты неопределенного поведения почти всегда вызваны кодом, генерируемым компилятором, взаимодействующим с операционной системой и / или оборудованием способами, не определенными разработчиком языка.Поэтому, если вы разыменуете указатель NULL, то, что произойдет, на самом деле не имеет ничего общего с компилятором, но будет зависеть от того, как базовая ОС / аппаратная часть справляется с недопустимым доступом к памяти.Если операционная система / аппаратные средства всегда решают эту проблему согласованно (например, через ловушку), то можно ожидать, что UB будет согласованным, но это не имеет ничего общего с языком или компилятором.

1 голос
/ 17 июня 2010

Многие такие поведения реализованы по-разному при компиляции с различными уровнями оптимизации или с режимом отладки или без него.

1 голос
/ 17 июня 2010

Нет, это отчасти причина того, что в стандарте существует неопределенное / определяемое реализацией поведение.Неопределенное поведение не обязательно будет одинаковым для нескольких компиляций одного и того же исходного кода на одном компьютере (скажем, с разными флагами оптимизации).

Комитет явно предпочитает четко определенное поведение.Поведение, определяемое реализацией, существует, когда комитет считает, что для некоторой концепции существует несколько реализаций, и во всех случаях нет причин предпочитать одну реализацию другой.Неопределенное поведение существует, когда комитет считает, что слишком сложно выполнять какие-либо обещания при разумной реализации.

Во многих случаях неопределенное поведение реализуется как нечто без проверки.Тогда поведение зависит от операционной системы, если она есть и если она замечает что-то менее кошерное.

Например, разыменование памяти, которой вы не владеете, не определено.В общем, ОС убьет вашу программу, если вы это сделаете.Однако, если звезды выровнены правильно, вам может понадобиться разыменовать память, которой вы не владеете в соответствии с правилами C ++ (например, вы не получили ее от new или вы уже delete d), но чтоОС считает, что вы владеете.Иногда происходит сбой, а иногда вы просто повреждаете память где-то еще в вашей программе, а иногда вы уходите незамеченными (например, если память не была возвращена).

Гоночные условия считаются неопределенными, и они печально известны тем, что отличаются во время разных запусков программы.Вы, вероятно, будете вести себя по-разному каждый раз, когда разбиваете свой стек, если ваша операционная система этого не замечает.

Double delete s не определены.Как правило, они приводят к сбоям, но тот факт, что они не определены, означает, что вы не можете полагаться на сбой.

1 голос
/ 17 июня 2010

Стоит отметить, что реализация указанного поведения Стандарта C ++ не на 100% идентична в компиляторах даже сегодня.Учитывая это, не стоит ожидать, что неопределенное или неопределенное поведение не зависит от компилятора.У вас больше шансов написать переносимый код, если вы просто придерживаетесь стандарта.

1 голос
/ 17 июня 2010

Это цель определения его как неопределенного ... это означает, что невозможно сказать, что произойдет, на другой или даже на той же платформе (с повторными тестами).

1 голос
/ 17 июня 2010

Я не знаю о неуказанном поведении (но, судя по названию, может быть, оно везде делает одно и то же плохое / злое, просто никто на самом деле не знает, что именно оно делает).Но из-за неопределенного поведения, я думаю, что он может вести себя ОЧЕНЬ по-разному на разных платформах или компиляторах.Я видел некоторые действительно странные coredumps на Solaris, которых не было в Ubuntu и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...