Clang SCOPED_CAPABILITY выдает «предупреждение: освобождение мьютекса «шкафчик», который не был удержан»

#c #multithreading #clang #mutex #static-analysis

Вопрос:

После попытки внедрить необходимые аннотации в существующую кодовую базу я не смог удалить, казалось бы, простое предупреждение. Я привел самый простой пример, и все равно никакой радости.

Я вырезал и вставил mutex.h заголовок точно так, как указано в Анализе безопасности потоков. Похоже, я не могу выполнить блокировку области действия без предупреждения. Вот код:

 #include "mutex.h"

#include <iostream>

// functions added just to complete the implementation
void Mutex::Lock()
{
}
void Mutex::GenericUnlock()
{
}

// test a scoped lock
void do_something(Mutex amp;m)
{
    auto locker = MutexLocker(amp;m);
    std::cout << "Hello, world!n";
}

int main(int argc, char** argv)
{
    Mutex my_mutex;
    do_something(my_mutex);
}
 

Компиляция с clang -o thread_static_analysis thread_static_analysis.cpp -std=c 17 -Wthread-safety выдает следующее предупреждение:

 thread_static_analysis.cpp:18:1: warning: releasing mutex 'locker' that was not held [-Wthread-safety-analysis]
}
^
1 warning generated.
 

Либо (1) я что-то упускаю, либо (2) это ложноположительный результат, который следует игнорировать до тех пор, пока проблема с реализацией clang не будет решена. Поиск таких проблем пока не дал никаких полезных результатов.

 clang version 10.0.0-4ubuntu1 
Target: x86_64-pc-linux-gnu
Thread model: posix
 

Ответ №1:

Насколько я понимаю, вы потенциально создаете копию временного MutexLocker объекта в

 auto locker = MutexLocker(amp;m);
 

(или анализ безопасности потоков думает, что вы его создаете). Затем временное устройство уничтожается и вызывает m.Unlock() . Затем в конце функции locker объект уничтожается и вызывается m.Unlock() снова (что приводит к ошибке двойного выпуска).

Комментарии:

1. Спасибо. Я только что проделал некоторую работу с операциями перемещения, и, очевидно, это застряло у меня в голове. В то время как компилятор должен сделать это назначением перемещения, с точки зрения статического анализа это назначение копирования, следовательно, временные. Я сменил его на MutexLocker locker(m); , и все хорошо.

2. @JohnJones на самом деле больше всего (всех?) компиляторы в любом случае избавились бы от временного (даже в режиме C 98), но TSA относится к конструкции консервативно.