2015-11-17 11 views
6

Alcune persone avvertono che le serrature possono essere mis-utilizzati da scrittura:È possibile creare istanze esplicite di variabili temporanee in C++?

std::unique_lock<std::mutex>(mutex); 

invece la seguente dichiarazione corretta:

std::unique_lock<std::mutex> lock(mutex); 

Vale a dire crea una variabile temporanea senza nome invece di una variabile locale. La variabile temporanea verrebbe distrutta immediatamente e sbloccerà prematuramente il mutex.

si veda ad esempio gperftools (line 321-324) header:

// Catch bug where variable name is omitted, e.g. MutexLock (&mu); 
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) 
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) 
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) 

Questa macro è stato scritto per proteggere ancora una volta tali casi d'uso.

Ma può ancora succedere? A quanto pare un sufficiente GCC o clang recente produrrà gli errori in questo caso:

#include <iostream> 

class Mutex {}; 

class Lock { 
public: 
    explicit Lock(Mutex */* dummy */) { std::cout << __PRETTY_FUNCTION__ << std::endl; } 
    ~Lock() { std::cout << __PRETTY_FUNCTION__ << std::endl; } 
}; 

int main() { 
    Mutex mutex; 
    { 
    Lock l(&mutex); 
    } 
    { 
    Lock(&mutex); // This line does not compile. 
    } 
    return 0; 
} 

E l'errore:

g++ foo.cpp 
foo.cpp:17:11: error: declaration of reference variable 'mutex' requires an initializer 
    Lock(&mutex); 
      ^~~~~ 
1 error generated. 

Qualcuno potrebbe esporre un caso Repro cui tale macro avrebbe raggiunto un vero e proprio bug? Non sono riuscito a inventarne uno finora.

+1

possibilmente correlate: http://stackoverflow.com/questions/914861/disallowing-creation-of-the -temporaneo-oggetti – BenC

risposta

4

In realtà si viene salvati dalla regola di disambiguazione per le cose-che-possono-essere-dichiarazioni (vengono analizzate come dichiarazioni, non come espressioni), insieme alla regola che richiede l'inizializzazione dei riferimenti.

Non vi farà risparmiare qui:

std::mutex m; 
int main(){ 
    std::unique_lock<std::mutex>(m); // m is a local default-constructed unique_lock 
} 

o qui:

struct C { Mutex m; } c; 
int main() { 
    Lock(&c.m); // Constructs and destroys a temporary lock. 
} 
+0

Per il primo esempio, è molto confuso che se std :: mutex è dentro main se non viene compilato ma se il mutex è esterno lo fa. Potresti approfondire quale tipo di schema sono problematici qui? –

+0

@ThomasMoulard 'std :: unique_lock (m);' è esattamente equivalente a 'std :: unique_lock m;' poiché viene analizzato come una dichiarazione. Dovrebbe essere abbastanza ovvio ora perché non si compila se il mutex si trova all'interno di 'main'. –

+0

ok mi sento stupido ora;) grazie! –

Problemi correlati