Ограничить беспорядок, вызванный неопределенным поведением?

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

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

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

Кроме того, я полагаю, 'что хорошая практика кодирования' сильные информативные комментарии каждые несколько строк, надлежащего добавления отступа и отладки дампов регулярно.

5
задан Ritwik Bose 12 January 2010 в 06:14
поделиться

4 ответа

Неопределенное поведение не обязательно оставляет компилятор с несколькими альтернативами. Чаще всего просто делает что-то, что не имеет смысла.

Например, возьмите этот код:

int arr[2];
arr[200] = 42;

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

Теперь представьте, как вы собираетесь обнаружить эту ошибку. Как это собирается на поверхность? Это может никогда , похоже, не вызывает никаких проблем. Возможно, нам просто так происходит, чтобы написать в память, которая сопоставлена ​​на процесс (поэтому мы не получаем нарушение доступа), но никогда не используется (так что ни одна другая в программе не будет прочитать наше значение мусора, или перезаписать то, что мы написали ). Тогда кажется, что программа без ошибок, и работает просто хорошо.

Или это может ударить адрес, который даже не сопоставлен с нашим процессом. Тогда программа немедленно уходит.

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

10
ответ дан 18 December 2019 в 08:28
поделиться

Я не уверен, что есть формальное определение «неопределенного поведения», но после хороших стандартов кодирования может уменьшить двусмысленность и привести к меньшему количеству дефектов компиляции и выполнения.

Тем не менее, получение двух программистов договориться о том, какие «хорошие стандарты кодирования» является сложным и подверженным ошибкам.

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

1
ответ дан 18 December 2019 в 08:28
поделиться

Как я понял из прочтения, неопределенное поведение - это результат того, что компилятор на момент компиляции остался с несколькими неидентичными альтернативами.

Хотя это может быть один источник неопределённого поведения, Вы говорите слишком абстрактно. Вам нужен конкретный пример того, что Вы имеете в виду под "неидентичными альтернативами во время компиляции".

Если под "следовать строгой практике кодирования" Вы имеете в виду не использовать логику, приводящую к неопределенному поведению, то да (потому что неопределённого поведения не было бы). Отследить ошибку из-за неопределённого поведения может быть проще, а может и нет, чем отследить ошибку, вызванную логической ошибкой.

Обратите внимание, что код, приводящий к "неопределенному поведению", все еще является легальным кодом на языке Си++. Я считаю это классом кода/логики, который очень редко следует использовать, когда "неопределенное поведение" предсказуемо для данной программы на данной платформе с заданной реализацией. Найдутся случаи, когда то, что язык считает "неопределенным поведением", на самом деле будет определено для конкретной среды/набора ограничений.

1
ответ дан 18 December 2019 в 08:28
поделиться

Во-первых, некоторые определения стандарта C ++ 03:

1.3.5 Поведение, определенное внедрением

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

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

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

1.3.13 Невыполненное поведение

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

Хотя неопределенное поведение можно назвать UB, я никогда не видел этого, а UB всегда означает undefined поведение. На протяжении всего стандарта являются заявления, аналогичные «Doing X, - неопределенное поведение», но иногда вы вступаете в случай, который просто не покрывается.

Чтобы поставить определение еще один способ, если у вас есть неопределенное поведение где угодно, то все ставки выключены . Что касается стандарта, ваша программа может сделать что-либо от приглашения ваших свеконов на выходных Superbowl до , работающих . Из-за самого природы UB вы не можете проверить для него, и вы не можете ожидать никакой помощи от компилятора. (Хотя для некоторых тривиальных компиляров общих ошибок обычно принимают диагностику.)

Обычно что-то определяется как UB, потому что он просто не имеет смысла логически (например, доступа к массиву вне границ), но и часто, потому что это потребует Реализация, чтобы сделать слишком много работы, чтобы предотвратить - часто во время выполнения. Помните, что C ++ получен из C, и способность производить высокооптимизированные программы - это главная цель обоих языков. С этой целью языки откладывают программиру, чтобы убедиться, что код правильный в этих ситуациях, связанных с «вы не платите за то, что вы не используете» принцип.

Итак, наконец, UB плохой, очень плохо; Избегайте этого на всех расходах. Тем не менее, тяжелая часть UB не зная, что она является или при каких обстоятельствах это происходит; Тяжелая часть распознает, когда вы вызываете UB. Например:

std::string s = "abc";
char& c = s[0];
cout.write(s.data(), s.length());
c = '-';

выглядит совершенно разумно, верно? Нету, это UB, все же Это будет работать, как вы ожидаете по всем популярным реализациям.

7
ответ дан 18 December 2019 в 08:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: