• Топ 10 ошибок в C++ проектах за 2018 год
    0
    Не может быть, чтобы константа CursorShowing равнялась 0, ведь буквально парой строк выше она инициализирована значением 1.

    Вот тут, кстати, видна разница между отдельным инструментом статического анализа и статическим анализатором, встроенным в IDE. Ведь в IDE вы бы сразу в точке предупреждения нажали "перейти к определению символа" и обнаружили бы причину в ту же минуту. Не пришлось бы долго разбираться и даже создавать тикет в баг-трекере.


    Если же действительно в анализаторе ошибка, будет легче понять, где она. Так как анализатор переиспользует ту же процедуру разрешения символа, что и функция перехода к объявлению, вы сразу поймёте, ошибка в анализе или в разрешении символов.

  • Как мы в IntelliJ IDEA ищем лямбда-выражения
    +1
    Попытаемся хотя бы английскую версию выкладывать на Хабр. К сожалению, перевод делать не всегда хватает времени.
  • Как мы в IntelliJ IDEA ищем лямбда-выражения
    +7
    Приходится, работа такая. Интересно, что с выхода восьмой Джавы по материалам этой главы спецификации исправили десятки багов и в компиляторе javac, и в компиляторе ecj, и в нашей IDE (хотя мы не полноценный компилятор, но вывод типов у нас должен быть полностью реализован). И ещё остались тёмные места, с которыми никто пока не разобрался. А иногда баги были в тексте спецификации, и сотрудникам Оракла приходилось править её. Это действительно трудно прочитать, правильно понять и правильно реализовать.
  • Пришло время Java 12! Обзор горячих JEP-ов
    +1

    Зачем? Оператор ?: есть, начиная с первой джавы.

  • Подсчитаем баги в калькуляторе Windows
    +1
    Ну это была утечка какого-то куска Windows 2000. Никто не гарантировал, что она полная и работоспособная.
  • Подсчитаем баги в калькуляторе Windows
    +5

    Вот, к примеру, мы пишем Java IDE. Вчера благодаря статическому анализу я обнаружил ошибку в процедуре рефакторинга Inline method. Код, на котором она проявляется, следующий (пытаемся инлайнить метод getTwice):


    class Test {
        enum Foo {
            BAR(getTwice(() -> {
                return getNum();
            }));
    
            Foo(int val) {}
        }
    
        static int getNum() {
            return 4;
        }
    
        static int getTwice(IntSupplier fn) {
            int x = fn.getAsInt();
            int y = fn.getAsInt();
            return x + y;
        }
    }

    Чтобы баг проявился, необходимо выполнение следующих условий:


    • Метод, который мы инлайним, должен возвращать значение
    • Метод, который мы инлайним, должен быть сложнее, чем просто один return, должно быть минимум два оператора в его теле
    • Метод, который мы инлайним, должен вызываться в конструкторе enum-константы
    • Среди аргументов этого метода должно быть лямбда-выражение
    • В лямбда-выражении должен быть полноценный return (простая expression-lambda не подойдёт)
    • return в этой лямбде должен возвращать результат другого метода (не константу, не арифметическую операцию, не переменную, а именно результат метода)

    Только при выполнении всех условий рефакторинг не срабатывает, а IDE выдаёт исключение. Рефакторингу больше 15 лет, им пользовались миллионы раз в самых разнообразных проектах, никто никогда не сообщил об этой проблеме. Возможно, никто просто ещё не написал настолько извратный Java-код. А статический анализатор играючи указал на ошибку в нашем коде. Исправление тривиальное, а вот чтобы сконструировать тест-кейс, где ошибка проявляется, я потратил около получаса. Стоило ли исправлять или дожидаться недовольного пользователя? Как считаете?

  • Подсчитаем баги в калькуляторе Windows
    +1

    Вот вам сорцы того самого калькулятора!

  • Подсчитаем баги в калькуляторе Windows
    +1
    V728 An excessive check can be simplified. The '(A && B) || (!A && !B)' expression is equivalent to the 'bool(A) == bool(B)' expression

    Вы же всё время хвастаетесь, что концентрируетесь на реальных багах, а не на стиле кодирования? А это чисто стилистическое. Некоторым людям трудно представить булево значение в контексте любой операции кроме &&, ||,!.. Ну просто мозг не поворачивается в эту сторону. Поэтому они пишут длинно.

  • Подсчитаем баги в калькуляторе Windows
    0

    Да, калькулятор сильно людям понравился. Вроде обычная статья от PVS-Studio, каких много, а столько плюсиков и комментариев!


    An odd precise comparison: ratio == threshold

    Мой опыт показывает, что эта инспекция слишком шумная и сделать её адекватной, то есть чтобы она указывала на реальные баги и не указывала на всякий мусор, довольно сложно. Но как минимум сравнения с нулём крайне редко бывают полезными предупреждениями. Я не помню ни единого случая из своей программистской практики, когда написанное программистом doubleValue == 0.0 приводило к багам, а abs(doubleValue) < someEpsilon исправляло эти баги. Рекомендую при нуле не предупреждать. Аналогично при единице. Среди тысяч найденных вами ошибок за годы работы есть хоть одна, где явное сравнение с единицей было проблемой?


    Теперь вернёмся к threshold. Эта переменная имеет значение 0 во всех формах и только в форме UnitConverter имеет значение 1. Соответственно данное сравнение тоже скорее всего безопасно.


    Даже не так. В случае если ActiveIfEqual == false, isActive = ratio > threshold. В случае если ActiveIfEqual == true, isActive = ratio >= threshold. Скажите, вы ругаетесь на операцию >=? Ведь здесь фактически она и есть.

  • Microsoft открыла код Калькулятора Windows
    +9

    Ну так это почти двадцать лет назад было. С тех пор технологии калькулирования-то сильно шагнули вперёд!

  • Microsoft открыла код Калькулятора Windows
    +4

    В старой утечке исходников Windows 2000 тоже был ещё старый калькулятор. Любопытно, что эти исходники лежат на гитхабе. Интересно, в курсе ли Микрософт?..

  • Лунная миссия «Берешит» – характеристики аппарата, серия маневров и самый длинный путь на Луну
    0

    Во, спасибо.

  • Лунная миссия «Берешит» – характеристики аппарата, серия маневров и самый длинный путь на Луну
    0

    Суть гравитационного маневра Вояджеров на пролёте мимо планеты, когда планета делится частью своего импульса, для меня вполне понятна, и существенная экономия топлива не вызывает сомнений. При таком манёвре вообще можно обойтись без затрат топлива. Тут же ситуация выглядит по-другому: космический аппарат уже движется по эллиптической орбите вокруг данной планеты, и просто так она поделиться импульсом не может. В каких точках орбиты включение двигателя помогает? Важно ли движение Земли вокруг Солнца или наличие Луны для такого манёвра?


    Вероятно тут речь об эффекте Оберта. Или нет?

  • Лунная миссия «Берешит» – характеристики аппарата, серия маневров и самый длинный путь на Луну
    0

    Интересно, а почему постепенно увеличивать апогей выгоднее, чем сразу разогнать до второй космической? И насколько выгоднее в терминах расхода топлива или стоимости миссии?

  • Релиз-кандидат JDK 12: Shenandoah, G1, JMH, Arm64. Баги в Swing наносят ответный удар
    +1

    Обсуждают неспеша, но как-то нет уверенности, что даже в 13 завезут.

  • Открытый курс «Deep Learning на пальцах»
    0
    но тратить время на изучение совершенно не нужного мне недоязыка смысла не вижу.

    Иногда полезно выходить из зоны комфорта.


    А вообще всё в ваших руках. Изучите тюториалы на питоне, а потом переделайте их на джаву. Сами лучше разберётесь, и другие вам будут благодарны. А если книгу выпустить, на этом ещё и заработать можно.

  • Строители против синтаксиса Java
    +1
    Так это проблема системы code-review, требуйте фича-реквест! Хорошая система могла бы резолвить вызов конструктора и оставлять подсказки.
  • Строители против синтаксиса Java
    0
    Как раз для HashMap (если религия не позволяет Java 9 или Guava) совершенно несложно написать в своём проекте свой нормальный билдер и использовать его.
  • Ищем ошибки в исходном коде Amazon Web Services SDK для .NET
    +1

    Например, чтобы хранить объекты в списках и искать/удалять там? Иногда линейный поиск вполне достаточен. Ну и в целом, чтобы иметь возможность сравнивать объекты. Иногда это нужно без хэш-таблиц. Если объект при этом ещё IComparable, его можно хранить в упорядоченных множествах без хэшкода.

  • Ищем ошибки в исходном коде Amazon Web Services SDK для .NET
    +1

    Ну и варнинги про нереализованный хэшкод люди не сильно любят. По хорошему стоит выдавать его только если где-то в проекте этот объект действительно используется как ключ для хэша. А если нет, зачем парить мозги разработчикам, отвлекая от реальных проблем?

  • Ищем ошибки в исходном коде Amazon Web Services SDK для .NET
    +2

    State19 — очевидно автогенерённый код лексера по грамматике, это мусорный варнинг. Автогенерённый код надо исключать из анализа.

  • Внедряйте статический анализ в процесс, а не ищите с его помощью баги
    0
    > Я не согласен, что первый шаг – это статический анализ, а только второй компиляция. Я считаю, что проверка компиляции в среднем быстрее и логичнее, чем сразу гонять «более тяжелый» статический анализ.

    В моей практике эти два шага идут одновременно и неразрывно с редактированием кода. После каждой правки кода автоматически в фоне IDE находит и ошибки компиляции (не компилируя на самом деле, но это и не важно) и предупреждения статического анализа. Там есть расстановка приоритетов, хайлайтинг ошибок обычно вперёд успевает завершиться, поэтому формально «сперва компиляция». Но обычно разница во времени меньше секунды, для человека это непринципиально.
  • PVS-Studio для Java
    +1
    С чеккастами дофига проблем из-за этого, кстати. В данном случае он больше враг, чем друг. Инспекции вида «cast may fail» практически всегда получаются очень мусорными на байткоде, репортя места, где каста не было вообще в сорцах.
  • Внедряйте статический анализ в процесс, а не ищите с его помощью баги
    0
    Как насчёт чтобы в условном build.gradle версия была указана конкретная, но при появлении новой версии робот на CI сам обновляет этот файл и коммитит обновлённый build-скрипт, возможно, разрешая на следующей сборке храповику прокрутиться назад? Тогда будет и обновление, и воспроизводимость.
  • PVS-Studio для Java
    +7

    Ваши примеры по большей части неактуальны. Джава-компилятор довольно глупенький и не делает таких умностей при компиляции в байткод, оставляя это джиту. Но как человек, посвятивший немало времени и сил анализу именно байткода, могу подтвердить, что идея от konsoletyper не пролезет. Даже для чистой джавы часть информации никаким образом оттуда не вытащишь, а часть наоборот добавляется зазря. С другими языками вроде Котлина всё ещё хуже. Компилятор может спокойно добавлять заведомо недостижимые ветки, которых в исходном коде не было и я могу это выяснить статически. В результате выдаётся предупреждение о проблеме, которой нет в исходниках. Вдобавок усложняется репортинг ошибок: у меня из отладочной информации есть только номер строки. А если строка длинная, и в ней три ошибки, попробуй-ка спозиционируйся.


    Реальные примеры проблем такие. Ошибки с возможной инверсией приоритетов операций дают ложные сработки, если в исходнике были явные скобки, которые говорили "да, я хочу именно этого". Безусловный выход из цикла не поймаешь, потому что в байткоде такой цикл не отличишь от if. Саппрессить варнинги очень сложно. Стандартная аннотация @SuppressWarnings не попадает в байткод вообще. Дженерик-параметры локальных переменных исчезают напрочь, их приходится восстанавливать эвристически. В исходниках могло быть написано что-то другое, и это иногда влияет на предупреждения. Про типы-пересечения вообще молчу. JVM про них ничего не знает.


    Кроме того, трудно найти вменяемый движок для работы с байт-кодом на достаточно высоком уровне, который бы поддерживался актуальным. Самому писать ещё труднее. Знаете, сколько всего надо поменять в движке вроде Spoon, чтобы поддержать конкатенацию строк из Java9+? Ничего не надо менять, в исходниках она не изменилась. А в байткоде там ад и погибель. Тот же дешугаринг лямбд наверняка ещё будет меняться. И при обсуждении реализации новых фич в джаве постоянно ребята из Оракла говорят "давайте через indy зафигачим". Если каждый инди-бутстрэп не распознавать, ваш байткод-анализатор будет очень уныло работать. А indy-бутстрэпы языко-специфичны. Наверняка если вы напишете анализатор байткода, тестируя его только на джава-коде, а потом возьмётесь за условный JRuby, вы поймёте, что ваш анализатор бесполезен. Там будет куча маленьких синтетических методов и через слово indy. Наконец, такой анализатор тупо надо тестировать на всех языках. Вам может казаться, что вы всё хорошо поддержали, но по факту вы поддержали только байткод, который генерирует javac. Встретите байткод от scalac, а там последовательность инструкций, которая сносит крышу движку — и всё пошло-поехало.

  • Проверка проекта CDK с помощью статического анализатора IntelliJ IDEA
    +1

    Ну а чего вы хотели? На то он и статический анализ. Было бы "всегда", я бы легко заставил Идейку решить проблему останова или доказать какую-нибудь недоказанную гипотезу теории чисел через такой варнинг :-)

  • PVS-Studio для Java
    0
    Всё правильно, но к нашей ситуации не относится. Ещё раз: asm0dey оспорил не предупреждение анализатора, а ухудшение производительности. Предупреждение анализатора он не оспаривал, поэтому утверждать, что анализатор внимательнее человека, в данном случае неверно. Я ровно это хотел сказать.
  • PVS-Studio для Java
    0
    Справедливости ради замечу, что анализатор не сказал «код работает чуть медленнее, чем мог бы», это уже человек, анализируя сообщение, пришёл к такому выводу. И asm0dey оспорил вывод человека, а не программы.

    В целом лишнюю проверку вида condition is always true компилятор нередко удалит так же легко, как анализатор заметит, поэтому не всегда имеется ухудшение производительности. В данном случае это, конечно, вряд ли сработает, но классифицировать такие случаи на вредные или нейтральные для производительности ваш анализатор вроде бы пока не научился :-)
  • PVS-Studio для Java
    0

    Бывает до смешного доходит. Пользователь присылает отчёт об ошибке, что в Идейке произошёл NullPointerException, мы смотрим стектрейс, а в этом месте сама Идейка подсвечивает код, что NullPointerException здесь возможен. Мол, «я же вас предупреждала, а вы!»


  • PVS-Studio для Java
    0
    Зато недавно мы сделали другую инспекцию, которая здесь срабатывает

    Перепутал ссылку на тикет, вот правильная.

  • Вышел FindBugs 3.0.1
    +4

    А-а-а! Некрофилы в комментариях!

  • PVS-Studio для Java
    +4

    Слушайте, ну если вы ожидаете от другого человека помощи, почему бы не сделать максимум работы самому? Если вы репортили баг, дайте хотя бы ссылку на него. У нас десятки тысяч открытых багов, мне сейчас идти и искать по вашему расплывчатому описанию?


    Кстати, если уж хочется привлечь внимание к тикету, есть способы лучше, чем писать разработчику совсем другой подсистемы. Например, твиттер. Особо хитрые жалуются на реддит. Ещё можно подговорить всех коллег проголосовать за баг. Только не сразу, а где-нибудь раз в неделю. Или можно время от времени писать дополнительные комментарии типа "проблема всё ещё актуальна в свежей версии, пожалуйста почините". Бывает, что работает. Только я вам этого не говорил :-)

  • PVS-Studio для Java
    0

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

  • Проверка проекта CDK с помощью статического анализатора IntelliJ IDEA
    +3

    Ай-яй-яй, прям по больному месту прошёлся! Ту ошибку мы уже тоже находим :-)

  • PVS-Studio для Java
    +5
    Позвольте! Идеевский анализатор вполне себе вдумчивый!
  • PVS-Studio для Java
    +7
    Специально отключают эту или все инспекции?

    Нет, не отключаем. Думаю, дело в том, что мы сильно толще вас. У нас только в мастер community 500 коммитов в неделю. А если ещё закрытая часть, которая не меньше. Представьте, что я улучшаю инспекцию, и она находит не одно или два, а сто новых подозрительных мест в коде. Это, кстати, не предел, мой личный рекорд — 800 новых предупреждений (речь о инспекциях категории Probable bugs, а не о каких-нибудь стилистических). Причём исправлять их надо вдумчиво, автоматом не получится. И что, бросать всё и начинать править? Часто проблемы находятся в коде пятнадцатилетней давности, который относится к поддержке какого-нибудь устаревшего фреймворка, у которого полтора пользователя теперь, и никто особо не в курсе даже что надо сделать в Идейке, чтобы метод с новым предупреждением выполнился. Да, можно тратить силы на это, но кажется, что можно потратить их более рационально.


    Ещё бывает, что мы импортируем кодовую базу. Например, кто-то разрабатывал плагин независимо, а потом мы договорились с автором, устроили его на работу и вставили его код к себе. Возможно, в нём немало предупреждений статического анализатора. Стоит ли в первую очередь их вычищать? Непонятно.


    Ну и, к сожалению, местами просто не хватает культуры. Я не коммичу код с новыми варнингами и стараюсь исправлять варнинги в любом коде, который трогаю. Но не все так делают, и это не форсируется у нас. Последнее время мы стали исправлять ситуацию. Некоторые инспекции у нас включены в так называемый список Zero tolerance inspections. Предупреждения от этих инспекций рисуются у нас кроваво-красным цветом, их сложно игнорировать. А если код с таким предупреждением закоммитить, то падает один из билдов, мне приходит письмо, и я с этим разбираюсь. Постепенно мы увеличиваем список таких инспекций, но, конечно, до идеала далеко. В частности, например, сообщений вида condition is always true пока слишком много, чтобы вот так легко их все исправить.

  • PVS-Studio для Java
    +21

    Да, тут напрашивается ответ, конечно :-) Во-первых, поздравляю вас с релизом, вы молодцы и делаете нужное дело. Пройдёмся по предупреждениям


    return capitalized / words.size() < 0.2;

    Это наглядный пример, что конкуренция — двигатель прогресса! Я заметил во время бета-тестирования, что вы тут умнее нас. Но очевидно, это не ваше достоинство, а наша недоработка :-) Я сообщил ответственному человеку, и тот уже исправил, в следующей версии будем это репортить.


    for (int index = count - 1; index >= 0; index++) {

    Мы знаем, что count в этом месте положительный и count - 1 неотрицательный. Кстати, в этом можно убедиться, нажав в IDE два раза Ctrl+Shift+P:



    Однако наш dataflow аккуратно вычисляет все переполнения и не считает, что условие цикла всегда истинно, потому что это не так.


    Зато недавно мы сделали другую инспекцию, которая здесь срабатывает. В принципе никакой разницы нет, с какого значения мы начинаем этот цикл, главное — это связка операторов в условии и инкременте. Связки >/++ и </-- — это почти всегда баги, о которых и сообщает новая инспекция. Будет в следующей версии. Так что эту проблему мы находим, хоть и по-другому.


    LoadingOrder.BEFORE_STR_OLD.equalsIgnoreCase(str) || и следующая

    Эта инспекция почему-то выключена по умолчанию. Надо будет разобраться с этим. Если работает нормально, то включим.


    for (int i = offset; i < endOffset; i++)

    Это мы видим, да. Но исправить всем лень. И, кстати, вы правы, я смог сломать Идейку, вызвав исключение в этом месте! Если кому интересно, надо в конце файла набрать


    /**
     * <p><

    Встать курсором между >< и нажать Enter! Если вы это повторите, у вас замигает в правом нижнем углу восклицательный знак. Report to JetBrains нажимать необязательно, мы уже в курсе :-) Вот, кстати, вам хороший пример пользы от статического анализа. Теперь-то исправим.


    if (buffer.length() > 0) {

    Это видим тоже. Не очень давно, кстати, может с прошлой версии. Думаю, в данном случае это действительно просто лишняя проверка.


    text.contains("\n") || text.contains("\r") || text.contains("\r\n");

    Вот это прям очень круто было. Если у вас dataflow это выводит, а не паттерн, то поднимаю лапки и признаюсь, что нам такое слабо пока.


    if ("0".equals(text) || "0L".equals(text) || "0l".equals(text)) {

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

  • PVS-Studio и Bug Bounties on Free and Open Source Software
    +2
    Собственно, если кто-то из них займётся этим в свободное время, то мы не против и желаем им удачи. Главное только, чтобы это их от основной работы не отвлекало :)

    Мне кажется, это странный подход. Во-первых, если ваш сотрудник найдёт реальный баг и получит баунти, это хороший маркетинговый результат. Одно дело теоретическая возможность, а другое — реальная проблема, которую авторы продукта посчитали достаточно значимой, чтобы оплатить. Этим вполне можно хвастаться. А во-вторых, это тестирование. Проверяя новые проекты всегда находишь, что бы улучшить в анализаторе. Где-то видишь ложную сработку и понимаешь, что её можно исключить статически. Где-то сработка нормальная, но сообщение о баге можно улучшить. Где-то вместо двух варнингов разумно выдать один, чтобы уменьшить количество шума. Поэтому мне кажется вполне допустимым, если сотрудники долю рабочего времени (например, до десяти процентов) тратить на поиск багов в проектах, возможно даже получая за это вознаграждение. Относитесь к этому как владелец ресторана относится к чаевым, которые получают официанты.

  • Время конференций! Подводим итоги 2018 года
    0

    Joker был в Питере, а не в Москве :-) Рад, что вам понравились наши паззлеры. Приезжайте в Новосибирск на CodeFest!

  • Как писать юнит-тесты, если совсем не хочется
    0

    Слева кабель-каналы на стене, уродство. Справа они наверняка спрятаны в стену. Это хорошо.