Pull to refresh

Comments 53

А есть версия PVS-Studio и CppCat под Linux? А когда будет?

К сожалению, нет, извините.

© www.viva64.com/ru/a/0085/#ID0E3SAE
Однако вы говорите что у вас есть PVS под Linux. Кому верить? :)
Тут должен быть анекдот про крестик и трусы
К нас нет PVS-Studio под Linux как готового продукта. У нас есть внутренняя command-line версия, собираемая под Linux. Компании могут заключить с нами контракт на адаптацию PVS-Studio под их систему сборки, их редактор и так далее. Никаких публичных версий. Только контрактные работы.
Ну, одно дело «нет вообще», а другое — «есть, но за отдельные деньги».
Просто по предыдущим статьям я думал что даже если сильно захотеть то под linux pvs не собирается.
Есть подозрение что «за отдельные деньги» вам соберут PVS Studio и под Mac OS, вопрос в том, сколько ноликов будет у слова «отдельные».
Согласен, но есть разница между «даже не начинали это делать» и «оно есть, но надо много заплатить». Вряд-ли заказчик будет ждать пол-года, пока pvs портируют под нужную платформу
UFO just landed and posted this here
Возможно, но пока в планы это не вписано.
Я еще и под МК пишу, интересно было бы попробовать анализатор.
Так почему-бы его и не попробовать тогда? :)
А у меня вся разработка на mac os. Чтобы проверить, это надо толи компьютер с виндой найти, толи виртуалку с линуксом поднять.

А расскажите в общих чертах подключить к такому проекту?

Там тонкость, что это ОС со своей системой сборки и кросс-компиляция для arm. Собираются проекты из папок внутри example(например https://github.com/contiki-os/contiki/tree/master/examples/ipv6/simple-udp-rpl), и к маленькому файлу с логикой работы подключается все окружение — сетевой стек, ОС, библиотеки.

1)Как проверять только свой код(тот, который в папке simple-udp-rpl)? А то, боюсь, утону в предупреждениях со всей операционки. Насколько я понимаю, можно без моего кода проверить, установив параметр «игнорировать существующие ошибки», а потом добавить его?
2)Куда в этих мейкфайлах найти, куда вклиниваться с анализатором? Или я усложняю, и это гораздо проще?

P.S. Кстати, если интересно проверить «ОС для интернета вещей», то могу поучаствовать, рассказать, как она собирается, дать комментарий по местам найденных ошибок и так далее.
А вы сообщили авторам проекта о найденных ошибках?
Можно поинтересоваться, как получилось, что clang нашел данные ошибки, несмотря на проверку кода вашим же анализатором?
Точно так же, как PVS-Studio находит ошибки в Clang, хотя они сами себя собирают и проверяют. Ссылки на проверки есть в начале статьи. Кстати, мы заодно Clang свежий проверили. Надо будет заметку сделать «PVS-Studio наносит ответный удар».
Это еще что. Нет-нет, да и найдется клиент, который спрашивает: «А вы ГАРАНТИРУЕТЕ, что если мы купим PVS-Studio, то у нас в коде не будет ни одной ошибки?». Так и хочется ответить, что если бы так было, то мы бы первые купили себе PVS-Studio.
Я как-то слышал возражение, мол, ошибку показывает, а как исправить — нет. Не нашелся, что ответить. Так можно и до кнопки «сделай мне хорошо» докатиться.
Видимо, спрашивал менеджер? наверное, еще и эффективный…
Да, беседа на тему внедрения и необходимости оной.
По поводу ошибки при снятии константности. Я посмотрел ваш код, там нет никакой ошибки, просто лишняя строчка (как в случае с kind). Ну, если не считать за ошибку само снятие константности.
Для того, чтобы вернуть значение, совершенно не обязательно добавлять к нему константность обратно :)
А вы занимаетесь проверкой PVS с помощью самой PVS? Это был бы вполне логичный шаг.

К примеру, новый GCC собирается старым GCC, и прочее
www.viva64.com/ru/a/0085/#ID0EIVAE
Будьте внимательны в следующий раз. За этот вопрос уже многих заминусовали, так как статья не первая, и вопрос задавался миллионы раз.
Да ему даже не надо было FAQ читать: прямо в статье написано «и, конечно, статический анализ с помощью PVS-Studio» в списке методов, используемых для тестирования.
1. А вы уже работаете над внедрением проверок на указанные типы ошибок?
2. И почему PVS-Studio не нашла их раньше? Поиск таких ошибок не был предусмотрен в принципе, или был предусмотрен, но анализатор что-то смутило?
1. Пока нет, но надеюсь со временем то же самое будет находить и PVS-Studio.

2. Нет какого-то манускрипта, где описаны все паттерны ошибок, которые может и должен находить статический анализатор кода. Есть некоторые подборки (MISRA, CERT). Но это малюсенькая часть от того, что можно диагностировать. Вдобавок, стандарт Си++ эволюционирует.

Поскольку нет единого идеала, каждый реализует те диагностики, которые кажутся ему наиболее интересными. Часто одни и те-же паттерны лежат на поверхности и их поиск независимо реализуется в разных анализаторах. Но в целом — «кто во что горазд».

PVS-Studio хорошо ищет опечатки. Clang хорошо ищет неинициализированные переменные, нулевые указатели.

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

Надо просто смериться и использовать какой-то набор инструментов, которые дополняют друг друга. Тем более, не так уж все страшно, как я расписал. Например, у PVS-Studio и Cppcheck совпадает по диагностикам на 6%. Я считаю, что это очень хорошее число. Есть паттерны, которые все посчитали важными и реализовали их. И со временем, ситуация будет только улучшаться. Область статического анализа очень молода. Конечно, lint существует давно. Но, да простят меня любители, lint по нынешнем временам простенькая утилита.

Отвечу ещё на одну крамольную мысль. Например, я возьму 5 известных статических анализаторов. Но все они вместе могут находить только 2% ошибок, которые может обнаруживать статический анализ. Быть может лучше вообще не пользоваться статическими анализаторами?

Неправильный ход мыслей. Во-первых, никто не отменяет правило 80/20. Т.е. поддержка 2% паттернов может обеспечить выявление, скажем 50% ошибок, которые чаще всего допускают люди. Отличны результат. Во-вторых, неважно сколько найдено или нет. Главное, анализатор даёт выигрыш больше, чем он стоит.
Кстати, у вас траблы с 5.18 версией когда проверяются *.i (-save-temps) файлы приготовленные gcc в больших проектах, там где можно найти сгенерированные *.c файлы которые могли удалиться после конфигурирования или компилирования. Выкидывает ексепшион о непригодном символе в пути к файлу, после чего 50/50 падает весь анализатор или продолжает работу. 5.17 — все ок.
Напишу завтра, постараюсь с подробностями, но я проверяю достаточно хитрым способом.

Сейчас, к примеру, наконец то скопировались все *.i файлы ядра линукса(с практически всеми, которые были доступны в конфиге, дровами) из виртуалки на винду.
30%(из ~10400 файлов) проверило уже. Из того что явно бросается в глаза сейчас нашел вот что, копи-паст он такой :):

bchahce:
static inline bool bch_bkey_equal_header(const struct bkey *l, const struct bkey *r) {
return (KEY_DIRTY(l) == KEY_DIRTY( r ) &&
KEY_PTRS(l) == KEY_PTRS( r ) &&
KEY_CSUM(l) == KEY_CSUM(l)); // <===
}


btrfs:
if (!(fs_info->workers && fs_info->delalloc_workers &&
fs_info->submit_workers && fs_info->flush_workers &&
fs_info->endio_workers && fs_info->endio_meta_workers &&
fs_info->endio_meta_write_workers &&
fs_info->endio_write_workers && fs_info->endio_raid56_workers &&
fs_info->endio_freespace_worker && fs_info->rmw_workers &&
fs_info->caching_workers && fs_info->readahead_workers &&
fs_info->fixup_workers && fs_info->delayed_workers && // <===
fs_info->fixup_workers && fs_info->extent_workers && // <===
fs_info->qgroup_rescan_workers)) {
err = -ENOMEM;
goto fail_sb_buffer;
}


driver — rtl8821ae:
void rtl8821ae_dm_set_tx_ant_by_tx_info()
if (
(rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
(rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)) {
SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]);
}


Это только по 501 прошелся и за что глаз зацепился, проверка достаточно долгая.Помню вы говорили о том что ядро достаточно протестировано и проверено десятками анализаторов, так и есть, но вот его модули, не совсем.
Самая проблема это очень большое кол-во предупреждений на макросы, а в строенном в standalone редакторе макросы просто нереально найти и просмотреть, вот если бы запилили фичу с показом развернутого макроса было бы просто класс.
Но это фактически потребует от нас сделать собственную реализацию intelliSence, что, как вы понимаете, является не совсем тривиальной задачей, особенно учитываю необходимые для этого трудо-затраты, при весьма специфичном контингенте пользователей конкретно у Standalone.

Однако, никто не мешает вам уже сейчас использовать текстовый редактор (и intelliSense) из той же Visual Studio — создайте пустой Visual C++ проект, добавьте в него все необходимые заголовки \ исходники и откройте plog отчёт в плагине PVS-Studio. IntelliSence распарсит, хоть и не на 100%, какую то часть исходников, и у вас будет работать переход по include'ам \ определениям типов и т.п.

Если у вас нет Visual Studio, вы можете всё это сделать и в бесплатной Express версии, правда вы не сможете открыть там отчёт из PVS-Studio.
Так и делаю. Хорошо что еще в 2013 студии в проект можно перетаскивать просто папки, а не как в 2010 отдельными файлами.
Для мимопроходящих:
Если у вас нет Visual Studio, вы можете всё это сделать и в бесплатной Express версии, правда вы не сможете открыть там отчёт из PVS-Studio.
Есть уже Visual Studio Community 2013.
Забыл написать, проверяю свеженький 3.16
В общем, появилось время еще раз все перепроверить на наличие бага о котором написал, пришлось скачать свежий инсталятор с viva64.com и обновить 5.17. На тех проектах с препроцессорными файлами(*.i), которые у меня хранятся в архиве, 5.18 версия отработала нормально, как и 5.17. Странно, когда как на двух из них точно выдавало ошибку в процессе анализирования еще неделю назад. Вы сменили билд? Но я еще попробую над свежим kernel 3.17-rc1 на будущей недели, все-таки это занимает очень много времени и иногда приходится до 3 ночи сидеть. Если симптомы будут — обязательно напишу.
Блин, ребята, спасибо за все, что делаете. Надеюсь, что когда-нибудь ваши продукты будут доступны и в Linux.
Не понял вот это:
int A, B;
bool getA, getB;
Get(A, getA, B, getB);
int TmpA = A; // Clang: Assigned value is garbage or undefined
int TmpB = B; // Clang: Assigned value is garbage or undefined
if (getA)
  Use(TmpA);
if (getB)
  Use(TmpB);

Функция Get() может инициализировать переменные A и B. Инициализировала она их или нет, она отмечает в переменных getA, getB

Значит, Get принимает все параметры по ссылке и может поменять каждый? TmpA и TmpB передаются в Use тоже по ссылке и она может их менять? Иначе для чего было вводить эти переменные?
Не выглядел бы код значительно проще, если бы Get был не void, а возвращал bool?
int A, B;

if (TryGet(A)) {
    int TmpA = A;
    Use(TmpA);
}

if (TryGet(B)) {
    int TmpB = B;
    Use(TmpB);
}
Давайте не будем обсуждать и упрощать псевдокод. :)
Наверно эту мысль уже писали, но все-таки бОльшую часть проблем вызывают ошибки в логике работы алгоритмов, а не ошибки статического характера. Статические ошибки обычно легко повторяются и очень просто исправляются.
Мифы о статическом анализе. Миф второй – профессиональные разработчики не допускают глупых ошибок.

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

И как без статического анализа найти это?
www.viva64.com/ru/examples/V597/

Согласен, в случае с С++ это похоже на правду, т.к. это очень небезопасный язык. По поводу того же «выхода за границу массива», на Delphi, например, есть опция компилятора «Range checking», которая добавляет проверки на каждое общение к arr[i], что 0<=i<длины массива и если это правило нарушается, генерирует осмысленное исключение.
В целом, мы стараемся использовать т.н. «защитное программирование», чтобы обнаружить ошибки как можно раньше. Это означает, что в коде много Assert'ов, много перепроверок, проверок входных параметров, различных верификаций, которые выполняются всегда во время работы программы. Причем мы их не отключаем и в релизах. Как правило на скорости работы программы это никак не сказывается: время, затрачиваемое на эти проверки обычно составляет менее 1% времени исполнения остального кода. При этом время на отлов ошибок и разборки со странными багами экономится в разы.

PS По поводу минусов выше: я согласен, что внести при рефакторингах или просто по невнимательности тупую ошибку очень очень легко. И иногда она проявляется гораздо позже, бывает даже через месяцы, или в каких-то особых условиях. В этом плане статический анализ безусловно важен и полезен и у нас даже есть свой инструмент для него, правда анализирует он код Delphi и ориентирован он больше на ошибки, наиболее часто наблюдаемые именно в наших проектах (т.е. с учетом нашей статистики ошибок). Однако ошибок, возникающих из-за неверных алгоритмов или от невнимательности программиста, который забыл сделать какую-то нужную осмысленную логическую проверку (т.е. просто не написал какой-то нужный код, т.е. анализировать анализатором тут нечего), всё-таки на порядок больше.
Для C есть различные решения вроде -fsanitize=bounds (для случаев, когда размеры массива могут быть определены статически) (clang), -fsanitize=memory и -fsanitize=address (проверяют чтение из неинициализированной памяти (первый) и выход за границы массива и различные другие ошибки вроде использования памяти после освобождения (второй)). И ещё есть valgrind и аналоги. Всё‐таки, C/C++ — это языки программирования с огромным количеством различных программ для разработчиков, проверяющих всё, что только можно. Delphi такое и не снилось (хотя тот же valgrind можно использовать для любой программы, статические анализаторы и sanitizer’ы clang’а и gcc — нет).

Другой вопрос, что внедрение всех этих статических анализаторов, sanitizer’ов и отладчиков, с последующим анализом и исправлением, гораздо более трудоёмкий процесс, чем включение нескольких опций компилятора.
По поводу двух последних багов, которые не просто UB а самое настоящее падение.
Вы пробовали написать тесты на эти примеры?

Кажется что либо возможно написать такой С++ код который соответствует необходимым условиям для креша — и тогда он должен быть в тестах — либо анализатор (как и авторы кода!) запутался в логике и не понял почему условия недостижимы.
Тесты написать на эти функции не пробовал. Крайне сложно. Нужно подготовить в памяти дерево разбора, напихать в определённые структуры информацию о переменных, типах и так далее. Юнит тесты построены на уровне подсовывания анализатору фрагментов кода, на которых проверяется, что он находит нужную ошибку или наоборот не выдаёт ложное срабатывание. Однако, там работает очень много подсистем, которые могут оказывать влияние на расмотренные функции.

Например, как мы видим здесь, что-то отсеивает ситуации, когда об объекте что-то не известно и нулевой указатель никогда не появляется. Однако, это всё равно ошибка. Ведь те внешние механизмы могут поменяться или изменятся условия, когда вызывается ошибочная функция. Так что действительно, ни я, ни анализатор не может отследить почему условия недостижимы. Это везение очень хрупко и конечно нужно править код.
Немного досадно, что к тексту статьи, пропагандирующей применение статического анализа кода, не применялся статический анализ орфографии хотя-бы.
Особенно досадно, когда замечания пишут не в личную почту. Да и забавно, когда при этом комментатор в своих статьях пишет «Вобщем» или «всего-лишь».
Приятно, спустя столько лет, обрести столь внимательного читателя. Ошибки в заметке исправил, спасибо!

Твоя очередь =)

Хотелось бы уточнить про функцию GetBitCountForRepresntValueLoopMethod()
Находится ли эта функция в заголовочном файле или она статическая? Судя по отсутствию ключевого слова static, объявление функции вполне может быть находиться в заголовочном файле.
Если функция в заголовочном файле, то кто знает, с какими аргументами её могут запустить. Например, GetBitCountForRepresntValueLoopMethod(100, 100) должен привести к переполнению.
Обыкновенная функция в *.cpp файле.

>… то кто знает…
Я знаю. Нет никакой ошибки. Ложное срабатывание.
Присоединяюсь к просящим выпустить версию под линукс, тем более Вы не скрываете, что она у Вас готова. Вашему бизнесу, основанному на программистах под Windows, это точно не повредит, так как нельзя просто взять и проверить линуксовой версией Windows-only проект.

Приведу пример проекта, где так и поступили. Есть такой замечательный статификатор программ под линукс, Ermine. У них тоже закрытый код и программа платная, но опробовать ограниченную версию можно без проблем. Бинарники, сделанные этой версией, запускаются первые 30 дней, потом перестают работать. Кроме того, действуют скидки для разработчиков свободного софта. А начиналось у них всё с аналогичной программы под Windows (BoxedApp).
Sign up to leave a comment.