Unbehandelte Ausnahme bei Verwendung von std :: mutex anstelle von boost :: mutex

9

Ich versuche, einige der Boost-Abhängigkeiten in meinem Code loszuwerden und stattdessen die neuen C ++ 11-Funktionen (Visual Studio 2013) zu verwenden.

In einer meiner Komponenten habe ich boost::mutex zusammen mit boost::lock_guard<boost::mutex> benutzt und alles hat gut funktioniert. Wenn ich stattdessen std::mutex zusammen mit std::lock_guard<std::mutex> verwende, erhalte ich den folgenden Fehler, wenn ich von main() zurückkomme.

  

Nicht behandelte Ausnahme bei 0x7721E3BE (ntdll.dll) in GrabberTester.exe: 0xC0000005: Zugriff auf Leseort 0xA6A6B491 der Zugriffsverletzung.

Das eigentliche Projekt ist ziemlich komplex und es ist daher schwierig, ein vollständiges funktionierendes Codebeispiel zur Verfügung zu stellen, um dieses Problem zu reproduzieren. In meinem realen Projekt werden die Mutexe in einer gemeinsam genutzten Bibliothek verwendet, die zur Laufzeit geladen wird (die aber bereits entladen sein sollte, wenn ich von main() zurückkomme).

Meine Fragen sind:

  • Sind boost::mutex und std::mutex so konzipiert, dass sie sich absolut gleich verhalten?
  • Wenn nicht, was sind die Unterschiede? Was muss ich bei der Verwendung von std::mutex anstelle von boost::mutex ?
  • beachten?
  • In der Shared Library erstelle ich Threads mit dem boost::thread Framework. Könnte es sein, dass std::mutex nur mit std::thread s verwendet werden kann und nicht mit boost::thread s?
  • kompatibel ist?

Bearbeiten:

Eine Sache, die mir aufgefallen ist: Wenn ich die dynamisch geladene shared library entlade, braucht es etwas Zeit. (Die DLL greift auf die Hardware zu und es dauert einige Zeit, bis alles sauber heruntergefahren ist). Wenn ich zu std::mutex wechsle, sieht es jedoch so aus, als könnte die DLL fast sofort entladen werden, aber das Programm stürzt dann ab, wenn es von main() zurückkehrt. Ich habe den Eindruck, dass das Problem mit std::mutex speziell im Kontext einer DLL liegt.

Bearbeiten 2:

Sowohl die Anwendung als auch die DLL sind in der Debug-Konfiguration mit dem Toolset v120 frisch erstellt und statisch mit der Laufzeitbibliothek (/ MTd) verknüpft.

Bearbeiten 3:

Unten finden Sie den Callstack. Die Ausnahme scheint von irgendwo im Treiber zu kommen. Nur zufällig habe ich herausgefunden, dass es damit zu tun hat, welche Implementierung von Mutex ich benutze.

%Vor%

Bearbeiten 4:

Vielleicht ist das ein Fehler im OpenNI2 SDK, der nur unter diesen sehr speziellen Bedingungen beobachtet werden kann. Also habe ich das Openni-Tag zu dieser Frage hinzugefügt. Dennoch bleibt die Frage: Warum funktioniert es mit boost::mutex , aber nicht mit std::mutex ?

    
Robert Hegner 06.01.2015, 14:09
quelle

4 Antworten

4

Das Problem ist wahrscheinlich statische Init-Hölle, ich habe vor kurzem fast dasselbe durchgemacht. Hier ist, was geht:

  1. Sie haben einen statischen Mutex (könnte Mitglied einer Klasse sein, die statisch ist).
  2. Der doexit () - Code beginnt mit der Bereinigung Ihrer statischen Dateien.
  3. Der Mutex ist irgendwo in doexit ()
  4. zerstört
  5. Etwas benutzt den Mutex nachdem er zerstört wurde, oft in einem Destruktor.

Das Problem ist, dass Sie die Reihenfolge der Zerstörung für statische Objekte nicht wirklich kennen. Also wenn du hast:

%Vor%

....

%Vor%

Dann kann Ihr statischer Mutex bereits gelöscht / zerstört / deadbeef sein, wenn ~ StaticObjA () aufgerufen wird. Das Problem wird verschlimmert, wenn die Objekte in verschiedenen Kompilierungseinheiten definiert sind (d. H. In verschiedenen Dateien definiert sind).

Meine Empfehlung zum Lösen ist, zu versuchen, die Abhängigkeit von statischen Objekten zu reduzieren. Sie könnten versuchen, ein statisches Objekt zu haben, das sich um die Konstruktion / Zerstörung von allem anderen kümmert, so dass Sie die Reihenfolge der Ereignisse steuern können. Oder verwende einfach keine Statik.

    
Chris Desjardins 03.10.2015 14:44
quelle
0

Ich füge das gleiche Problem hinzu und was gelöst ist ... eine vollständige manuelle Reinigung + Neuerstellung! Überprüfen Sie das Löschen aller .obj-, .dll-, .lib-Dateien.

    
norisknofun 16.02.2015 15:44
quelle
0

Benutze nicht std :: mutex (oder recursive_mutex, ...) von Mircosoft !!!! Ich hatte ähnliche Probleme. Ich verwende VS2012.

Wenn Sie std :: mutex in einer DLL verwenden, dürfen Sie diese DLL nicht entladen. Weil Sie ein undefiniertes Verhalten erhalten. (in meinem Fall 0xC0000005: Leseort für Zugriffsverletzung ....). Oder Sie können die DLL nicht entladen. ("? Runtime?" erhöht den Ladezähler. Double FreeLibrary () entlädt die DLL)

    
Alexander Drichel 28.01.2016 13:22
quelle
0

Ich hatte ein ähnliches Problem, als mein Code versuchte, zweimal den gleichen Mutex zu sperren: Eine Funktion erlangte die Sperre und rief dann eine andere Funktion auf, die versuchte, eine Sperre für den gleichen globalen / statischen Mutex zu erhalten.

%Vor%     
Constantin Galbenu 06.06.2016 07:35
quelle