Почему нет предупреждения gcc/g++ для неиспользуемых временных файлов?

Рассмотрим следующий код:

void ListenerImpl::attach(boost::shared_ptr<ISubscriber> subscriber)
{
    boost::unique_lock<boost::mutex>(mtx);
    subscribers.push_back(subscriber);
}

void ListenerImpl::notify(MsgPtr msg)
{
    boost::unique_lock<boost::mutex>(mtx);

    //notify all subscribers
    BOOST_FOREACH(boost::shared_ptr<ISubscriber> subscriber, subscribers){
        subscriber->update(msg);
    }

}

(Это реализация шаблона наблюдателя, как описано в GoF.) В данном случае вмешательство пользователя состояло в том, чтобы защитить attach() и notify() от одновременного запуска, следовательно, boost::unique_lock. Целью было защитить subscribers контейнер.

Но действительно очень трудно заметить, что замки на самом деле просто временные (присмотритесь, имена для них не назначены). Таким образом, блокировка мьютекса будет немедленно снята, когда временный объект будет разрушен, то есть код не является потокобезопасным. Я ожидал бы в подобных ситуациях предупреждение компилятора. Что-то вроде "Неиспользованный временный".

Хуже того, cppcheck тоже не признает эту ошибку. (cppcheck: инструмент анализа кода a c/ C++ http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page)

Gcc выдает предупреждения о неиспользуемых переменных. Временная здесь - неиспользуемая переменная, и определенно результат невнимательности программиста. Итак, почему нет предупреждений в подобных случаях? Может быть, слишком сложно обнаружить такие ситуации?

3 ответа

Решение

Компилятор не выдает предупреждение, потому что вполне возможно, что вы обновляете некоторые static-member / global переменная внутри конструктора (которая является действительной и значимой). например:

struct A
{
  static int count;
  A () { count ++; }
};

Теперь, когда вы просто вызываете временное:

A();

Если такого обновления не происходит, компилятор не будет копаться в конструкторе A и проверьте, происходит ли что-то полезное. Это всегда предполагает действительный сценарий. Есть много таких случаев, связанных с временными.

Обратите внимание, что предложенное вами предупреждение также будет выдаваться для каждого it++;, который встречается во многих циклах.

iammilind уже упоминал, что иногда это намерение создать и немедленно разрушить временную температуру: когда есть побочные эффекты.

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

Поэтому в предложенном вами предупреждении будет много ложных срабатываний. Будет трудно найти подлинные предупреждения среди ложных.

Поэтому я ожидаю, что производители компиляторов решили, что их время лучше проводить в другом месте.

Хм.. я не уверен, но разве это нельзя защитить с помощью обычного C++?

class Mutex;
class Lock {
    Lock(Mutex *mutex);
};

int main() {
    Lock /* lock */ (&mtx);
    return 0;
}

Я получаю это предупреждение компилятора при компиляции с DJGPP:

C:\df>gxx -c a.cpp
a.cpp: In function 'int main()':
a.cpp:8:30: error: 'mtx' declared as reference but not initialized

Он прекрасно компилируется, если я раскомментирую "lock" и добавлю переменную mutex.

Так что, если ваша переменная "mtx" является указателем. Что произойдет, если вы измените его и передадите вместо него "&mtx".

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