Как определить поведение undefined

Есть ли способ узнать, имеет ли программа undefined поведение на С++ (или даже C), не запомнив всю спецификацию?

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

Ответ 1

Хорошие стандарты кодирования. Защитите себя от себя. Вот несколько идей:

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

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

  • Всегда используйте RAII.

  • Никогда не применяйте приведения стиля C! Никогда! - Я думаю, что там, как пара редких случаев, когда вам нужно сломать это, но вы, вероятно, никогда не найдете их.

  • Если вы должны reinterpret_cast или применить к void, используйте обертку, чтобы убедиться, что вы всегда выполняете листинг в/из того же типа. Другими словами, оберните указатель/объект в boost::any и нарисуйте указатель на него в нужное вам положение, а с другой стороны сделайте то же самое. Зачем? Поскольку вы всегда будете знать, какой тип reinterpret_cast, а boost::any будет принудительно применен к тому, что после этого вы выбрали правильный тип. Это самое безопасное, что вы можете получить.

  • Всегда инициализировать свои переменные в точке объявления (или в инициализаторах конструктора в классе).

Есть больше, но некоторые из них очень важны для начала.

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

Важно помнить, что универсально для всех языков:

сделать ваши конструкции легкими в использовании правильно и трудно использовать неправильно

Ответ 2

Во всех случаях невозможно обнаружить поведение undefined. Например, рассмотрим x = x++ + 1;. Если вы знакомы с языком, вы знаете это UB. Теперь *p = (*p)++ + 1;, очевидно, также UB, но как насчет *q = (*p)++ + 1;? Это UB, если q == p, но отличное от того, которое оно определило (если неловко выглядящее). В данной программе вполне возможно доказать, что p и q никогда не будут равны при достижении этой строки, но это невозможно сделать вообще.

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

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

Ответ 3

Инструменты анализа статического кода, такие как PC-Lint могут помочь здесь много.

Ответ 4

Ну, эта статья охватывает большинство аспектов.

Ответ 5

Я думаю, вы можете использовать один инструмент из coverity, чтобы обнаружить ошибки, которые приведут к поведению undefined.

Я думаю, вы могли бы использовать теоретические прокси-серверы (я знаю только Coq), чтобы убедиться, что ваша программа делает то, что вы хотите.

Ответ 6

clang пытается создать предупреждения при возникновении поведения undefined.

Ответ 7

Я не знаю ни одного программного средства для обнаружения всех форм UB. Очевидно, что использование ваших предупреждений компилятора и, возможно, lint или другой статической проверки кода может помочь много.

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

Ответ 8

Прост: не делайте то, что вы не знаете, что можете сделать.

  • Когда вы не уверены или имеете подозрительное чувство, проверьте ссылку

Ответ 9

К сожалению, нет способа обнаружить все UB. Для этого вам придется решить проблему с остановкой.

Лучшее, что вы можете сделать, это знать как можно больше правил, искать его, когда вы сомневаетесь, и проверять с другими программистами (через парное программирование, обзоры кода или просто вопросы SO)

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

Но в конечном итоге ни один инструмент не сможет обнаружить все это.

Дополнительная проблема заключается в том, что многие программы на самом деле должны полагаться на UB. Некоторые API требуют этого, и просто предположим, что "он работает на всех нормальных компиляторах". OpenGL делает это в одном или двух случаях. Win32 API даже не будет компилироваться в соответствии со стандартным компилятором.

Итак, даже если у вас есть волшебный инструмент для обнаружения UB, он все равно будет срабатывать по делам, которые не находятся под вашим контролем.

Ответ 10

Хороший компилятор, такой как компилятор Intel С++, должен уметь обнаруживать 99% случаев поведения undefined. Вам нужно будет изучить флаги и переключатели для использования. Как всегда, прочтите руководство.