Разрешено ли компилятору C ++ генерировать случайный код при обнаружении конструкции, которая классифицируется как неопределенное поведение?

Возможный дубликат:
Неопределенный, неуказанный и определенный реализацией поведение

Я пытаюсь углубить свое понимание неопределенного поведения в C ++. Предположим, что компилятор C ++ намеренно обнаруживает некоторые случаи неопределенного поведения - например, дважды изменяя переменную между двумя точки последовательности:

x++ = 2;

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

Согласно стандарту C ++, везде, где что-то классифицируется как UB, нет требований к тому, что происходит < / а>. Будет ли описанный воображаемый компилятор соответствовать стандарту C ++?


person sharptooth    schedule 24.11.2010    source источник
comment
Это был бы не очень популярный компилятор.   -  person Alex Brown    schedule 24.11.2010
comment
В принятом ответе на вопрос, на который вы ссылаетесь, говорится: «В основном, стандарт позволяет что-нибудь случится, когда вы вызовете неопределенное поведение (даже носовые демоны). А теперь скажите мне, почему мы не должны закрывать вашу как дурак?   -  person sbi    schedule 24.11.2010
comment
@sbi: Может быть, ты прав, но назальных демонов не так-то просто реализовать в компиляторе, и я предпочитаю сосредоточиться на реальных (даже если они маловероятны) вещах.   -  person sharptooth    schedule 24.11.2010
comment
@sharptooth: Ваш вопрос гласит: Разрешено ли компилятору ..., ответ гласит: В принципе, стандарт разрешает все, что угодно. Для меня это явный обман. Теперь я вижу, что в конце вопроса, выделенного мелким шрифтом, есть еще кое-что. Если это то, что вы на самом деле хотели спросить, возможно, вы захотите изменить заголовок своего вопроса, прежде чем он будет закрыт.   -  person sbi    schedule 24.11.2010
comment
@sbi: Что именно вы считаете мелким шрифтом в этом вопросе? Я постарался сделать это как можно более понятным. Я хотел бы знать, есть ли способ его улучшить.   -  person sharptooth    schedule 24.11.2010
comment
@sbi, извини. Я имел в виду острый зуб.   -  person Matthew Flaschen    schedule 24.11.2010
comment
@sharptooth: Честно говоря, я не знаю, что сказать, не повторяя себя. Ваш вопрос: разрешено ли компилятору ..., который покрывается вопросом, с которым вы связались (все разрешено), что делает это обманом, что заставило меня проголосовать за его закрытие. Если в этой логике есть что-то непонятное, я, честно говоря, не знаю, как это объяснить. Это я или ты?   -  person sbi    schedule 24.11.2010
comment
@sbi: Хорошо, теперь я понимаю вашу точку зрения. Может быть, вы правы, но я читал этот и многие другие вопросы, и моя цель - сосредоточиться на крайних, но конкретных примерах, потому что, хотя вы знаете, что более вероятно умереть по любой причине люди в целом более охотно платят за страховку от смерти от чего-то конкретного - так же, как в случае наводнений и землетрясений - google.com/   -  person sharptooth    schedule 24.11.2010
comment
В заголовке вы говорите о встрече с конструкцией, в то время как в тексте вы говорите намеренно обнаруживать, что гораздо более ограничено, и предлагаете, чтобы вы спрашивали, имеет ли компилятор право быть умышленно злонамеренным, если он должен это сделать? Это действительно твоя забота? Если это так, я не думаю, что вам нужно будет доказывать, что Стандарт запрещает это, прежде чем привлекать их к ответственности за злонамеренное злоупотребление вашей ИТ-системой.   -  person Tony Delroy    schedule 24.11.2010
comment
@Tony: Нет, меня это не касается. Я просто попытался найти крайний пример - преднамеренное использование случайного кода.   -  person sharptooth    schedule 24.11.2010
comment
@sharptooth: намеренно испускает случайный код, но не является преднамеренно злонамеренным ... нет ... Я могу пообещать вам, что это НЕВОЗМОЖНО (потому что случайный код имеет ненулевую вероятность - даже небольшую - совершить что-то вредоносное, и каждый разработчик компилятора знает Это).   -  person Tony Delroy    schedule 24.11.2010
comment
Неопределенное поведение дает разработчикам компиляторов еще большую свободу, чем это, факт, который любят использовать современные компиляторы. Такой метод, как uint32_t counts[64]; uint32_t shift(uint32_t *arr, uint32_t v, uint8_t s) { if (s < 64) arr[s]++; if (s >= 32) v=0; return v << s;}, вероятно, будет работать так, как ожидалось, практически во всех компиляторах, выпущенных до 2010 года или около того, даже при вызове как shift(counts, 1, 64);. Однако новый компилятор может очень хорошо перебрать слово за конец массива.   -  person supercat    schedule 16.04.2015


Ответы (4)


да. Стандарт не предъявляет требований нет, поэтому он может делать все, что захочет:

неопределенное поведение

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

В качестве примечания, это неопределенное поведение, но это не обязательно хороший пример. В g ++ 4.4.1 он откажется компилироваться с:

ошибка: требуется lvalue как левый операнд присваивания

потому что результат постинкремента не является lvalue.

person Matthew Flaschen    schedule 24.11.2010

По сути, да, если и только если эти 10 инструкций одинаково доступны. Рассмотрим следующий код:

int main () {
  if (false) {
    int x = 0; x++ = 2;
  }
  std::cout << "Hello, world" << std::endl;
}

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

(Этот вопрос не повторяется, потому что определение UB времени выполнения во время компиляции ранее не рассматривалось)

person MSalters    schedule 24.11.2010
comment
Это интересно. Почему компилятору не разрешается произвольно удалять программу после того, как он встречает единственный экземпляр UB? - person sharptooth; 24.11.2010
comment
Неопределенное поведение - это свойство времени выполнения с потенциально не причинным эффектом. Он должен быть в пути выполнения, чтобы иметь эффект (существует широкий класс UB, который зависит от данных, например, a [i] = a [j] ++). - person AProgrammer; 24.11.2010

Конкретный компилятор (если он не содержит ошибок) всегда будет вести себя одинаково (определенно без случайного кода) при обнаружении таких конструкций (если контекст кода не отличается).

На практике «неопределенное поведение» означает «разные компиляторы будут обрабатывать вещи по-разному».

Если вы хотите знать, будет ли ваш воображаемый компилятор по-прежнему соответствовать стандартам C ++? - думаю, да.

person Community    schedule 24.11.2010
comment
Не мог компилятор, обрабатывающий код, для которого поведение не определено, ввести этот код в свой AST, передать его через различные процессы обработки и оптимизации и, в зависимости от окружающего кода, уровней оптимизации, флагов компилятора и т. Д., Создать машинный код, который ведет себя по-другому или влияет на окружение иным образом. четко определенный код, такой, что если ведет себя иначе? Я не говорю, что это особенно вероятно, но есть ли у вас основания для такого однозначного вывода об обратном ...? - person Tony Delroy; 24.11.2010
comment
Привет ... Я сказал, если только контекст кода не отличается. Спрашивающий сказал - испустите десять полностью случайных машинных инструкций в созданный машинный код, который, как мне кажется, означает случайный код, даже если контекст тот же. - person ; 26.11.2010
comment
К сожалению, похоже, что существует философия, согласно которой компиляторы имеют право предполагать, что, если получение определенного ввода неизбежно вызовет неопределенное поведение, компиляторы должны предположить, что такой ввод не может произойти, и, следовательно, исключить код, который не имел бы никакой цели, кроме как обрабатывать такое поведение. Вход. Как следствие, Undefined Behavior не ограничивается также законами времени, но также и законами причинности (например, учитывая if (x != 0) foo(); y=1/x;, компилятор может опустить условную проверку перед вызовом foo, поскольку это не будет связано с обязательствами ... - person supercat; 13.07.2015
comment
... воздерживаться от вызова foo, когда x равен нулю. - person supercat; 13.07.2015

Из проекта стандарта / http://www.kuzbass.ru:8086/docs/isocpp/intro.html / [1.3.12]

[Примечание: допустимое неопределенное поведение варьируется от полного игнорирования ситуации с непредсказуемыми результатами до поведения во время трансляции или выполнения программы в задокументированной манере, характерной для среды (с выдачей или без выдачи диагностического сообщения), до прекращения трансляции или выполнения ( с выдачей диагностического сообщения). Многие ошибочные программные конструкции не приводят к неопределенному поведению; они должны быть диагностированы. ]

Определенно не перечисляет вставку случайных инструкций, и трудно утверждать, что аспект «диапазонов от» будет включать решение о вставке случайных инструкций как находящихся в любом месте континуума между перечисленными поведениями. ;-)

person Tony Delroy    schedule 24.11.2010
comment
Хм ... Там задокументировано - я думаю, это может позволить случайные инструкции. Но тогда я не могу понять, чем это отличается от поведения, определяемого реализацией. - person sharptooth; 25.11.2010
comment
В любом случае я задал вопрос по этому поводу - заголовок stackoverflow.com/questions/4274763/ - person sharptooth; 25.11.2010