Предупреждение об обнаружении безымянной переменной

Недавно я встретил ошибку в проекте C++, связанную с неназванной защитой области, как в этом вопросе:

LockGuard(mutex);

Посмотрите простую демонстрацию.

Такую ошибку очень сложно обнаружить при просмотре изменений, а также сложно отладить. Я хотел бы использовать автоматическую проверку в CI.

Есть ли какое-либо предупреждение компилятора (gcc, clang, cl) или инструмент статического анализа, который может указать на проблему?

Во-первых, это анализируется как std::lock_guard<std::mutex> mutex; и вызывает ошибку компиляции, поскольку lock_guard не является конструируемым по умолчанию. Если я заменю (...) на {...}, то Clang на -stdlib=libc++ выдаст предупреждение (потому что конструктор nodiscard), а MSVC также выдаст предупреждение (видимо, есть специальное предупреждение?).

HolyBlackCat 16.07.2024 12:55
clang-tidy замечает это.
Jesper Juhl 16.07.2024 13:26

я удалил твой UPD. Дискуссия в комментариях не была бесполезной. Необходимо было уточнить вопрос. Вот для чего нужны комментарии

463035818_is_not_an_ai 16.07.2024 14:24
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В новых версиях стандарта C++ есть атрибут [[nodiscard]], который также можно применять к конструкторам.

Итак, если вы напишете класс, подобный следующему:

template<typename M>
class my_lock_guard {
public:
    [[nodiscard]] my_lock_guard(M& mutex)
        : m_mutex(mutex)
    {
        m_mutex.lock();
    }

    ~my_lock_guard()
    {
        m_mutex.unlock();
    }

private:
    M& m_mutex;
};

тогда следующий код выдаст предупреждение компилятора в достаточно новых компиляторах:

static std::mutex my_mutex_var;
static int global_var;
void foo()
{
    my_lock_guard<std::mutex>{my_mutex_var};
    global_var = 42;
}

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

Таким образом, для всех классов RAII этого типа, которые вы пишете самостоятельно (т. е. классов, которые просто существуют для использования в текущей области видимости, но никогда не затрагиваются после создания), просто добавьте [[nodiscard]] ко всем конструкторам, и это автоматически вызовет соответствующие предупреждения компилятора.

К сожалению, этот атрибут еще не был добавлен в достаточное количество частей стандартной библиотеки C++ в доступных на данный момент версиях стандартов. Ни lock_guard, ни scoped_lock, ни unique_lock, ни shared_lock не имеют [[nodiscard]] конструкторов вплоть до C++23 включительно. Для этих классов стандартной библиотеки вам придется использовать другие инструменты. Как упоминалось другими людьми в комментариях, clang-tidy, очевидно, также может обнаруживать проблемы такого типа, независимо от наличия атрибута. Я бы по-прежнему рекомендовал, чтобы вы в любом случае использовали этот атрибут в соответствующих случаях, потому что тогда вы уже увидите эту проблему на уровне компилятора.

(Также обратите внимание, что my_lock_guard выше — это минималистичный пример, а не полная замена std::lock_guard; пожалуйста, не используйте мой пример в рабочем коде.)

Другие вопросы по теме