CERT.CONC.MUTEX.DESTROY_WHILE_LOCKED

ロックされている間はミューテックスを破棄しないでください。

ミューテックスオブジェクトは、共有データを同時アクセスから保護するために使用されます。ロックを待機しているスレッドがブロックされている間にミューテックスオブジェクトが破棄されると、クリティカルセクションと共有データは保護されなくなります。スレッドが所有しているミューテックスオブジェクトをプログラムが破棄した場合や、ミューテックスオブジェクトを所有しているときにスレッドが終了した場合、プログラムの動作は不定になります。

脆弱性とリスク

ロックされている間にミューテックスを破棄すると、無効な制御フローやデータ破損が発生する可能性があります。

軽減と防止

ロックされている間はミューテックスを破棄しないでください。

コピー
  #include <mutex>
  #include <thread>
  
  const size_t maxThreads = 10;
  std::mutex m2;
  using namespace std;
  
  void do_work(size_t i, std::mutex *pm) {
    std::lock_guard<std::mutex> lk(*pm);
   //printf("hello");
   // Access data protected by the lock.
 }
 
 void start_threads1() {
   std::thread threads[maxThreads];
   std::mutex m1;
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i] = std::thread(do_work, i, &m1); // Uncompliant code.If you use mutex 'm1' to start
   }                                            // several threads, when one thread ends, this mutex
 }                                              // will be destroyed while other threads 
                                                // are still locking this mutex.
 void start_threads2() {
   std::thread threads[maxThreads];
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i] = std::thread(do_work, i, &m2); //compliant code, by using global mutex variable.
   }
 }
 
 void run_threads() {
   std::thread threads[maxThreads];
   std::mutex m3;
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i] = std::thread(do_work, i, &m3);
   }
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i].join();                         // compliant code, by using join method.
   }
 }