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

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

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: инструмент анализа кода ac / c ++ http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page)

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

Ответы [ 3 ]

8 голосов
/ 29 июня 2011

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

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

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

A();

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

0 голосов
/ 30 июня 2011

хмм .. Я не уверен, но разве это нельзя защитить с помощью обычного 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".

0 голосов
/ 29 июня 2011

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

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

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

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

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

...