Comments 64
- gcc — 33 предупреждения, ценных — больше половины, включая особо ценные вроде
operation on ‘d’ may be undefined [-Wsequence-point]
ELM_Answer[d-12] = AnswerBuffer[0][d++];; - cppcheck — 36 предупреждений, два
The scope of the variable 'b' can be reduced
, остальные —Prefer prefix ++/-- operators for non-primitive types
, причем непримитивными он обозвал то ли указатели, то ли enum, то ли вообще int. - pvs выдал 6 предупреждений двух типов
V640 The code's operational logic does not correspond with its formatting. The statement is indented to the right, but it is always executed. It is possible that curly brackets are missing.
иV560 A part of conditional expression is always true:
.
На честный запуск ознакомительной версии pvs потратили неделю. Пытались и под windows и под linux… Ответов на написанные тогда письма — ждем до сих пор. В конце концов плюнули и запустили нечестно — правила позволяют один раз проверить в бесплатном варианте, а потом удалить нужные строки.
Так что pvs полезен, но безумно дорог, cppcheck — обычно не оправдывает время на разбор его предупреждений, а -wall -wextra — золотая серединка. Кстати, лучше всего именно в инкрементальном режиме, то есть устранять все выданные предупреждения.
Попробовали на проекте в полторы тысячи строк.Для проекта в полторы тысячи строк плотность ошибок составляет 0-25 ошибок на 1000 строк. Так что ставить эксперименты на столь малых проектах имеет мало практического смысла. В них вообще может не быть ошибок.
Так что pvs полезен, но безумно дорог,Это заблуждение, которое продолжает тиражироваться. Компании приходят и приобретают инструмент и только некоторые обсуждают скидки. Есть конечно те, кто говорит, что дорого. Но им просто не нужен инструмент и им был бы дорог и CppCat за 250$. Поэтому про это нет смысла говорить.
PVS-Studio в рассчёте на 1 программиста дешевле, чем оплата аренды за квадратные метры в офисе, которые занимает программист. Если взять общие расходы на содержание программиста, то стоимость PVS-Studio вообще не заметна на их фоне.
Ну что же, будем считать, что на самом деле PVS-studio работает намного хуже того великолепного результата, что он показал в нашем тесте.
Что касается цены, то разумней на те же деньги (пара миллионов в год уже или больше?) нанять тестера, а то и двух.
PVS-Studio в рассчёте на 1 программиста дешевле, чем оплата аренды за квадратные метры в офисе, которые занимает программист
Цена PVS-Studio примерно равна аренде офиса на всю фирму. Не все живут в Москве и располагаются с видом на Кремль.
PVS-Studio в рассчёте на 1 программиста дешевле, чем оплата аренды за квадратные метры в офисе, которые занимает программист
Кстати, это хороший критерий, кому есть смысл покупать PVS-Studio. Есть офис с видом на Кремль (или Гудзон) — есть смысл покупать. Офис дешевле — нет смысла.
Иными словами, PVS-Studio — это как малиновый пиджак или розовый лаборджини — нечто, показывающее престижность владельца. Ну Apple заработала миллиарды на такой стратегии, так что почему бы и нет.
Если бы ещё дотянули до продукта… Потому как качество документации — ниже плинтуса, а время ответа на письма… Ну мы уже полгода ждем.
у cppcheck сплошняком бесполезные
За 4 года использования не увидел у Cppcheck ни одного бесполезного предупреждения.
Для GCC -Wall и -Wextra недостаточно, есть еще много флагов, которые нужно включать вручную.
Использую gcc -Wreturn-type -Wpointer-sign -Wsign-compare -Wshadow -Wpointer-arith -Wimplicit -Werror (список не сразу таким стал)
Недавно пришлось столкнуться с clang — там добавил -Wno-logical-op-parentheses -Wno-parentheses
Вообще думаю что набор актуальных (и возможно-индикаторов-бага) предупреждений у каждого свой, в зависимости от привычек и стиля написания кода.
-Werror — спорный вопрос, не всегда это удобно, особенно при отладке, когда сознательно закомментарена часть кода и вылезают предупреждения о неиспользуемых параметрах и переменных.
#define suchar
звучит как угрозаЖесть какая (я про второй случай).
Интересно, реально ли разработать специальную диагностику для всяких "#define true false"?
В любом случае, "#define true false" это какое-то вредительство и не стоит о нём специально думать. Если уж кто-то захочет навредить, он придумает как это сделать, чтобы это было и не заметно и скрылось от анализаторов.
На практике больший интерес представляют случаи неумышленно неправильного написания #define. Например, могут быть забыты скобки. Мы уже выявляем некоторые такие ситуации (см., например, V1003) и будем развивать анализатор в этом направлении и дальше.
Ну просто пример, который вы привели, был именно такого уровня, просто чуть подлее. Типа #define true (rand()%100000!=0).
Можно попробовать сделать наоборот
#define false true
habrahabr.ru/post/197266
В легаси коде
//md3_man.cpp
typedef char* as_if_string;
...
extern "C" as_if_string ReadPictureName(const LPSTR package, const UINT8 ID, as_if_string Extention)
далее, PVS ругается на
//texman.c
char* path;
...
path=ReadPictureName("Posters",i,"");
и пишет
V647 The value of 'int' type is assigned to the pointer of 'char' type. Consider inspecting the assignment: 'path = ReadPictureName("Posters", i, "")'. texman.c 165
Проверьте, есть ли объявление функции ReadPictureName в texman.c. Скорее всего нет, а раз так, считается, что функция возвращает int. Как следствие, имеем красивую 64-битную ошибку.
Нет, функции из ж.cpp там вызываются из ж.c без их объявления.
И как это правильно исправить?
Неужели, поменять char на int?! в офигении
Или описать вызываю функцию явно?
Добавил в textman.c строку:
char* ReadPictureName(const LPSTR package, const UINT8 ID, char* Extention);//it is external! in MD3_Man.cpp
Сообщение об ошибке исчезло :)
(не уверен, что сделал всё правильно правильно, так как после миграции с VC++ 6 на VC++ 2013, проект сейчас вылетает в совсем другом месте)
Правильно — сделать MD3_Man.h с этим прототипом и заинключить его в обоих исходниках.
А то, что MD3_Man написан на C++, а texman на обычном простом C, какой на это эффект окажет?
PS в комментариях к MD3_Man.h почему-то написано
//USE extern!!!!!!! just for myself
Тогда так
#ifdef __cplusplus
extern "C"
#endif
char* ReadPictureName(const LPSTR package, const UINT8 ID, char* Extention);
Что означает комментарий не знаю, это в конце концов ваш код и вам лучше надо его знать.
Вспомнил, почему добавлено
typedef char* as_if_string;
потому что без этого
extern "C" char* ReadPictureName(const LPSTR package, const UINT8 ID, char* Extention);
при вызове
path=ReadPictureName("Posters",i,"");
не работал корректно и выдавал ошибку.
PS комментарий, вообще не помню откуда, но писать в комментариях "just for myself", вряд ли бы мне пришло в голову (подозреваю, что это легаси, но, точно не уверен).
у вас нет объявления функции в файле textman.c, и С компилятор считает, что функция возвращает int параметр.
т.е. это все равно, что вы напишите
int a = 2;
char *c = a;
Вас же не смутит тут такое же предупреждение?
З.Ы. чисто теоретически интересно, за что минусуют сейчас комменты топик стартера?
Эм, я не понял, а -Wimplicit компилятора вы УЖЕ проигнорировали/отключили? Если да, то в этом и есть корень вашей проблемы, а если нет, то это и правда проблема анализатора, но я в этом сомневаюсь.
Как же приятно, когда за такими вещами следит сам компилятор!
let mut text = vec![0; 256];
let mut caption = vec![0; 256];
load_string(&mut text);
load_string(&mut text);
message_box(&text, &caption);
warning: variable does not need to be mutable
--> src/main.rs:9:9
|
9 | let mut caption = vec![0; 256];
| ^^^^^^^^^^^
|
= note: #[warn(unused_mut)] on by default
Хм, переменные используются одинаково а варнинг только про одну из них, посмотрю ка повнимательней.
TCHAR text[512], caption[128];
LoadString(GetModuleHandle(NULL),…, text, 512);
LoadString(GetModuleHandle(NULL),…, text, 128);
MessageBox(NULL, text, caption, MB_ICONERROR | MB_OK);
1. Второй вызов LoadString получает размер массива 128, но он не соответствует _countof(text)
почему тут не ловится V512. A call of the 'Foo' function will lead to a buffer overflow or underflow.?
Вообще передавать константу — плохо. в одном месте поправил а в другом забыл.
будет удобно, если анализатор в подобные места будет тыкать.
2. Не обрабатывается код возврата LoadString — в случае ошибки в переменных будет мусор
и MessageBox может уронить программу.
2) Кажется это было сделано специально. Уж очень никто не проверяет результат LoadString. :) Я изучу этот вопрос.
Собрали под мониторингом, проанализировали, впихнули в сонар и наслаждайтесь.
У нас продукты наверное 4-5 компайлерами собираются — и все в один проход срабатывает.
А то что IronHead рассказывает — скорее всего силно криворукие люди были. В свое время мы даже splint под Code Composer Studio гоняли.
Любите статический анализ кода