ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
27 апреля
826709 Топик полностью
Николай Коровин (24.03.2018 11:28, просмотров: 119) ответил VVB на Свершилось! Отечественная разработка статического анализатора кода для встраиваемых систем управления PVS-Studio. Рад, что они наконец пришли в эту нишу, надеюсь, что не зря.
ОК. А теперь давайте не для сферического коня, а для реальных случаев. Хочется понять осмысленность всего этого. Вот три реальных бага, my most recent ones. Уродовать свой код так, чтобы он соответствовал какому-то навязанному феншую -- с этим сразу досвиданья по двум причинам: 1) как тут правильно сказали, это отвлекает от реальной аккуратности и подменяет её псевдоцелью, т. е. изначально (до вылавливания) багов больше становится, и не факт, что вылавливание это перекроет; 2) все три этих бага возникли НЕ из-за "слишком изящного", "слишком быстрого" или "слишком оптимального" кода, а по банальной неаккуратности. Итак, вот эти баги и мой вопрос: мог ли какой-то анализатор действительно их предупредить и ругнуться строчкой ворнинга на стадии сборки, пусть даже с небольшим количеством ложных тревог? Баг первый. Структура A содержит указатели на массивы B, C и D. Там лежат вектора размерностью b, c и d в количестве n. Я знаю, что n в данной задаче всегда 2 и статично объявляю B[max_b * 2], C[max_c * 2] и D[max_d]. Пока извне приходили данные с d<=max_d/2, всё было нормально. Но первый же тест с большим d всё свалил. Баг был легко найден и прибит (глянул объявления и увидел, что двоечку забыл), но я вот что-то даже не пойму, как его можно было заранее "пропалить". Нам даже b, c и d фактические неизвестны до запуска. Баг второй. Записал на диск массив: первый элемент как __int64, остальные -- как word разности между предыдущим и следующим. При считывании скопипастил код записи и заменил запись на чтение: прочитал в промежуточную переменную __int64, затем со второго элемента массива апдейтил промежуточную переменную этими диффами и заносил в массив. Саму промежуточную переменную занести в первый элемент ессно забыл :) Тоже баг на сорок копеек, запустил и увидел, что первый элемент нуль или мусор. Но данные нигде не используются, отдаются "на улицу", причём записанные в весьма разнородный блоб, а "массив" на самом деле -- (мояструктура*)(адресблоба + смещениемассива)[элементмассива].злополучныйQWORD и (мояструктура*)(адресблоба + смещениемассива)[элементмассива].всёостальное забивать на данной стадии не надо. Как догадаться, что (мояструктура*)(адресблоба + смещениемассива)[0].злополучныйQWORD должен быть определён, а (мояструктура*)(адресблоба + смещениемассива)[элементмассива].чтоугодноещё -- нет? Баг третий. Вот этот сумел из моих рук выскользнуть! Если бы у нас была классическая ответственность по принципу "тесты прошло -- отвечаю не я", я бы получил фобосвгрунт на реальной технике. Но мы (пока что) отталкиваемся от здравого смысла, а не бюрократии, поэтому баг не вышел за пределы лаборатории. Тесты типа "отчитаться и подобострастно улыбнуться Начальству" он натягивает "на раз". Я скопипастил код под новые структуры данных, приходящие извне. Они отличались символически, но пришлось переставить две операции. К сожалению, я забыл, что у меня одна из переменных знаковая, и преобразование типа произошло не там, где надо. В результате операция битового смещения вправо была совершена не над беззнаковой, а над знаковой переменной. Данные формально выглядели правильными и физически от правильных тоже отличались очень мало, после всех вычислений исказился какой-то мохнатый знак после запятой. Мою профессиональную паранойю, к счастью, баг не проскочил и даже до пред-испытаний (моделирования системы в комплексной работе в разных условиях) не дошёл, не заставив коллег делать лишнюю работу. Там в этом знаке должно было быть примерно равномерное статистическое распределение, а вышли какие-то пики. Ессно, я стал разбираться, сфиги они там, и его нашёл. Можно ли как-то догадаться, что биты с карасятого по поросятый в теле битного (даже не байтного!) блоба являются беззнаковым числом и на попытки его знакового смещения надо ворнинг выдать?