Как определить неопределенное поведение - PullRequest
12 голосов
/ 10 июня 2010

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

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

Ответы [ 10 ]

16 голосов
/ 10 июня 2010

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

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

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

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

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

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

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

Есть и другие, но это очень важные для начала.

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

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

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

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

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

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

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

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

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

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

clang старается выдавать предупреждения при обнаружении неопределенного поведения.

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

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

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

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

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

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

Мне неизвестен какой-либо программный инструмент для обнаружения всех форм УБ.Очевидно, что использование предупреждений вашего компилятора и, возможно, lint или другой статической проверки кода может очень помочь.

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

0 голосов
/ 10 июня 2010

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

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

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

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

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

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

0 голосов
/ 10 июня 2010

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

  • Если вы не уверены или у вас рыбное чувство, проверьте ссылку
0 голосов
/ 10 июня 2010

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

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