Ich habe vor kurzem valgrind --tool=helgrind
auf meinem Projekt ausgeführt und eine Warnung "mögliches Datenrennen" erhalten, was meiner Meinung nach bedenklich war. Aber selbst dieses einfache Testprogramm führt zu dieser Nachricht:
Kompiliert mit g++-4.9 -p -g -std=c++11 -pthread -O3 test.cpp
ist die Ausgabe von valgrind --tool=helgrind ./a.out
:
Meine Frage: Kann ich das ignorieren? Wenn ja, wie können diese Warnungen unterdrückt werden?
Ich stieß auch auf diese Warnung und überprüfte den Quellcode von libstdc ++ für GCC 4.8 ( /usr/include/c++/4.8/future
) auf Kubuntu 14.04. Ich habe keinen Fehler gefunden. Der Zustand future
enthält unter anderem einen Ergebniszeiger, einen Mutex und eine Zustandsvariable. future<T>::wait()
sperrt den Mutex und überprüft, ob der Ergebniszeiger Null ist. Wenn dies der Fall ist, wartet es auf die Bedingungsvariable (die den Mutex ebenfalls in einer atomaren Operation entsperrt). Bei promise<T>::set_value()
(oder set_exception()
, schätze ich) sperrt der Code den Mutex, setzt den Ergebniszeiger, entsperrt den Mutex und ruft notify_all()
auf condition variable
auf. Daher warnt Helgrind, weil der Mutex nicht gesperrt ist, wenn notify_all()
aufgerufen wird. Der Code ist jedoch immer noch sicher, da der Mutex zum Setzen des Zeigers gehalten wird, was die einzige Möglichkeit ist, das Ergebnis der Prüfung in future<T>::wait()
zu ändern. Die Benachrichtigung außerhalb der Lebenszeit von lock_guard
kann eine Optimierung sein (den Mutex so kurz wie möglich halten). Es führt leider zu dieser Warnung. Die Verwalter von libstdc ++ werden wahrscheinlich zögern, ein Patch zu akzeptieren, weil a) ein Patch die Leistung verringern würde, wenn auch nur geringfügig, und b) es nicht beheben würde, wenn es nicht kaputt ist. Daher empfehle ich, Helgrind zu unterdrücken.
Bitte beachten Sie, dass ich einige Interaktionen vereinfacht und verkürzt habe, insbesondere future
und promise
delegieren die tatsächliche Arbeit an versteckte Implementierungsklassen, set_value
verwendet zusätzlich once_flag
, um gleichzeitige Aufrufe zu synchronisieren usw.
Siehe auch diesen Thread, meine Antwort darauf und den genauen Kommentar zu meiner Antwort von Cubbi (etwas, das ich übersehen hatte): Warum? Sowohl die Benachrichtigungs- als auch die Wartefunktion einer std :: condition_variable benötigen einen gesperrten Mutex
Tags und Links c++ pthreads valgrind packaged-task