3

Мы пишем код внутри ядра Linux, поэтому, как бы то ни было, я не смог заставить PC-Lint/Flexelint работать с кодом ядра Linux. Слишком много встроенных символов и т. Д. Но это побочный вопрос.Ловля переполнения левой смены константы 1 с использованием предупреждения компилятора?

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

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

unsigned long long foo; 
unsigned long bar; 

[... lots of other code ...] 

foo = ~(foo + (1<<bar)); 

Дальнейшее ОБНОВЛЕНИЕ описание проблемы - даже с баром, ограниченным 16, все еще проблема. Уточняя, проблема заключается в неявном int-типе константы, который, незапланированный, делает сложное выражение нарушающим правило, что все вычисления выполняются с одинаковым размером и подписью.

Проблема: «1» недолго длиннее, но, как константа малого значения, по умолчанию используется значение int. Поэтому даже если фактическое значение бара никогда не превышает, скажем, 16, все же выражение (1<<bar) будет переполняться и разрушать весь расчет.

Возможно правильное решение: вместо этого напишите 1ULL.

Есть ли известный предупреждающий флаг компилятора и компилятора, который укажет на эту (пересмотренную) проблему?

+0

Независимо от того, какой размер int, если бар слишком большой, сдвиг не определен (я думаю, что-то плохое, во всяком случае). Кажется, вы просите компилятор предупредить вас о переменном втором операнде для переключения на int. Но вы говорите, что проблема в том, что «1» недолго: вы не хотите предупреждать о переменном сдвиге на долгое время? Я не понимаю, почему авторы компилятора ожидали, что это предупреждение будет полезным, а общие предупреждения о переменном втором операнде в << приведут к большому количеству ложных срабатываний. –

+0

@onebyone: Предполагая, что 'int' - 32 бита, а' long long' - 64, '~ (foo + (1 << bar))' работает только для '0 <= bar <32', а' ~ (foo + (1LL << bar)) 'работает для' 0 <= bar <64'. Я предполагаю, что OP хочет получить предупреждение, когда первое будет написано вместо последнего. – ephemient

+0

Несомненно, но он хотел бы, чтобы это предупреждение в случаях, когда foo является int и bar логически ограничено (но не по типу), чтобы быть либо 1, либо 2? Как насчет того, где foo длинный, а бар - 1 или 2? Предупреждения для умножения или добавления бара к любой подписанной константе, так как результат переполнения не определен?Компилятор обычно не может идентифицировать логические ограничения, поэтому я ожидаю, что любые такие предупреждения будут сильно подвержены ложным срабатываниям. Это не значит, что это плохая идея, я просто размышляю, почему трудно определить, что это должно быть, и низкий приоритет для компиляторов в любом случае. –

ответ

1

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

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

+0

Я посмотрю на ваш сайт. Я понимаю, что, предлагая бар в 64, я ввел в заблуждение. до 16. Даже тогда есть проблема, что линт ловит, но я ищу gcc, чтобы поймать. Проблема не в слишком большом сдвиге, как таковая. Это сложное выражение с непреднамеренными, несколькими типами в нем. – talkaboutquality