Какие инструменты для статического и динамического анализа кода на C++ ты использовал?

«Какие инструменты для статического и динамического анализа кода на C++ ты использовал?» — вопрос из категории Тестирование, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В своей практике для обеспечения качества кода на C++ я активно использую комбинацию статических и динамических анализаторов.

Статический анализ (SAST):

  • Clang-Tidy / Clang Static Analyzer: Мои основные инструменты, интегрированные в CI/CD. Они отлично находят potential bugs, нарушения code style (например, Google C++ Style Guide), упрощения кода (modernize-* checks).
    # Пример запуска
    clang-tidy -checks='*' myfile.cpp -- -std=c++17
  • Cppcheck: Использую для поиска специфических проблем, которые могут ускользнуть от других анализаторов, например, ошибок с границами массивов или утечек ресурсов.
  • PVS-Studio: Мощный коммерческий анализатор, который глубоко анализирует код и находит сложные ошибки (VLA, copy-paste). Использую его для периодического глубокого аудита критичных модулей.

Динамический анализ (DAST):

  • Valgrind (Memcheck, Helgrind): Незаменим для отладки утечек памяти, ошибок работы с неинициализированной памятью и проблем с многопоточностью (data races) в Linux.
    // Код, который Valgrind Memcheck обнаружит как ошибку
    int* ptr = new int(42);
    delete ptr;
    // Ошибка Use-after-free
    std::cout << *ptr << std::endl;

    Запуск: valgrind --leak-check=full ./my_program

  • AddressSanitizer (ASan), UndefinedBehaviorSanitizer (UBSan): Инструменты от LLVM, которые я предпочитаю за скорость (в сравнении с Valgrind). Они компилируются вместе с кодом и отлавливают ошибки памяти (разыменование nullptr, выход за границы массива) и неопределённое поведение (переполнение знакового целого, сдвиг на отрицательное число).
    # Компиляция с AddressSanitizer
    clang++ -fsanitize=address -g -O1 myfile.cpp
  • Google Test / Catch2 с профилировщиком покрытия (gcov, llvm-cov): Для модульного тестирования и отслеживания coverage. Цель — поддерживать высокий процент покрытия ветвлений (branch coverage) для критического кода.

В рабочем процессе эти инструменты интегрированы в систему сборки (CMake) и пайплайн CI, что позволяет отлавливать проблемы на ранних этапах.