C++ - Exception-Handling In Kritischen Abschnitt (pthreads)
[Edit: (kopiert aus einem Kommentar), Wie es sich herausstellt, lag das problem woanders, aber ich danke Ihnen allen für Ihre Eingabe.]
Ich haben ein gemeinsames container-Klasse, die verwendet eine einzelne mutex zu sperren, push() und pop () - Funktionen, da ich nicht möchte, gleichzeitig zu ändern, den Kopf und Schwanz. Hier ist der code:
int Queue::push( WorkUnit unit )
{
pthread_mutex_lock( &_writeMutex );
int errorCode = 0;
try
{
_queue.push_back( unit );
}
catch( std::bad_alloc )
{
errorCode = 1;
}
pthread_mutex_unlock( &_writeMutex );
return errorCode;
}
Wenn ich dies im debug-Modus, alles ist peachy. Wenn ich im release-Modus, bekomme ich die Abstürze in etwa die Zeit, wenn das Treiber-Programm beginnt, schieben und knallen "gleichzeitig". Funktioniert der try/catch-block sofort einen Ausstieg, wenn es fängt eine std::bad_alloc-Ausnahme? Wenn dem so ist, sollte ich schließen Sie den Rest der Funktion in einem finally-block?
Außerdem ist es möglich, dass die langsameren debug-Modus nur gelingt, weil meine push() und pop() ruft eigentlich nie zur gleichen Zeit auftreten?
- Was ist die Art des Absturzes? Und könnte Sie posten die
pop()
Funktion zu?
Du musst angemeldet sein, um einen Kommentar abzugeben.
In C++ verwenden wir Resource Acquisition Is Initialization (RAII) zum Schutz vor Ausnahmen.
Ist das eigentlich Bombardierung, nachdem eine Ausnahme? Weit mehr wahrscheinlich von Ihrem Ausschnitt, dass Sie nur noch schlechte Synchronisation statt. Das beginnt mit dem Namen des mutex: "writeMutex". Dies ist nicht zur Arbeit gehen, wenn es auch ein "readMutex". Alle Lesen, gucken und Schreiboperationen gesperrt werden müssen, indem die gleichen mutex.
Nicht. Wenn ein std::bad_alloc geworfen wird, innerhalb der
try {...}
block, den code in diecatch {...}
block ausgelöst wird.Wenn Ihr Programm tatsächlich abstürzt, dann scheint es, wie Sie entweder Ihren push_back Aufruf werfen einige Ausnahme andere als
bad_alloc
(das ist nicht behandelt in Ihrem code), oder diebad_alloc
wird geworfen, irgendwo außerhalb dertry {...}
block.Durch die Art und Weise, sind Sie sicher, dass Sie wirklich wollen, um mit einem try...catch-block hier?
plus
was macht die pop Aussehen
erstellen Sie eine lock-wrapper-Klasse, die automatisch freie die Verriegelung, wenn Sie den Bereich verlässt (wie in RAII Kommentar)
c++ nicht endlich (vielen Dank an Herrn stoustrop wird stroppy)
ich würde fangen std::exception oder gar keine (Enten Kopf nach unten für die Flammen-Krieges). Wenn u fangen Sie keine, dann müssen Sie den wrapper
Bezüglich release/debug: ja, Sie werden oft feststellen race-Bedingung zwischen den zwei Arten von builds. Wenn Sie sich mit der Synchronisierung, Ihre threads laufen mit verschiedenen Ebenen der Ausbildung. Gut geschrieben threading werden meist gleichzeitig ausgeführt werden, während schlecht geschrieben einfädeln der Fäden wird in einer sehr synchron relativ zueinander. Alle Arten von Synchronisierung Ausbeute einige level synchrones Verhalten. Es wie, wenn die synchronen und Synchronisation kommen aus der gleichen Wurzel Wort...
Also ja, da die etwas unterschiedliche Leistung zwischen debug und release, jene Punkte, wo die threads synchronisieren kann manchmal dazu führen, schlechten code zu manifestieren, in eine Art von bauen und nicht die anderen.
Müssen Sie die Verwendung von RAII
Grundsätzlich bedeutet dies, dass mit dem Konstruktor/Destruktor zu sperren/entsperren der Ressource.
Dadurch ergibt sich, dass der mutex wird immer freigeschaltet, auch wenn Ausnahmen vorhanden sind.
Sollte man nur mit einem mutex für den Zugriff auf der Liste.
Auch wenn Sie eine nur-lese-mutex, die von einem thread, der nur liest. Das bedeutet nicht, es ist sicher zu Lesen, wenn ein anderer thread die Aktualisierung der Warteschlange. Die Warteschlange könnte in gewissen zwischen-Zustand, verursacht durch einen thread aufrufen von push (), während ein anderer thread versucht, ti navigieren eine invlide Zwischenstand.
PS. Ich hasse die Verwendung von führenden Unterstrich.
Obwohl technisch ist es OK (vorausgesetzt, member-Variablen) es ist so einfach zu Durcheinander, dass ich lieber nicht zu pre-pend '' zu idnetifiers. Sehen Was sind die Regeln über die Verwendung eines Unterstriches in einem C++ - Bezeichner? für eine ganze Liste von Regeln zu tun über '' in Bezeichner-Namen.
Locker
bin ich mir nicht so sicher, was zu tun mit Fehlerbehandlung. Ich das Tor, ich bin OK mit der eine Ausnahme auslösen, wenn die Sperre nicht, aber ich würde auch gerne wissen, Wann der unlock nicht, aber ich fühle mich nicht wirklich gut über das werfen von Ausnahmen von der dtor. Und die Schaffung einesclose
Methode, die Art von Niederlagen der Zweck des habens ein wrapper, der schließt den mutex auf die Bereiche' Ende. Was wäre dein Ansatz dazu?Vorherigen code-Beispiel mit Locker-Klasse hat ein großes problem:
Was tun Sie, wenn und wenn pthread_mutex_lock() fehlschlägt?
Die Antwort ist, Sie müssen eine Ausnahme an dieser Stelle, aus dem Konstruktor, und Sie können gefangen werden.
Fein.
Allerdings
Laut c++ - exception-Spezifikationen werfen eine exception aus einem Destruktor ist ein no-no.
WIE gehen SIE mit pthread_mutex_unlock AUSFÄLLE?
Ausführen von code unter jedem instrumentation software dient keinem Zweck.
Sie haben zu Recht-code, das funktioniert nicht führen Sie es unter valgrind.
In C funktioniert es einwandfrei:
Aber weil c++ ist eine software, die Abtreibung gibt es einfach keine vernünftige Möglichkeit, den Umgang mit threaded kodiert Ausfälle mit jedem Grad der Gewissheit. Gehirn-Toten Ideen wie Geschenkpapier pthread_mutex_t in einer Klasse, fügt eine Art state-variable ist nur, dass - brain dead. Der folgende code funktioniert einfach nicht:
Und der Grund dafür ist, dass nach pthread_mutex_unlock() gibt in diesem thread sehr gut in Scheiben geschnitten werden aus der cpu - verdrängt. Das bedeutet, dass die .fehlgeschlagen öffentliche variable wird immer noch falsch. Andere threads anschaut, wird es falsche Angaben, die state-variable sagt keine Fehler, mittlerweile pthread_mutex_unlock() ist fehlgeschlagen. Auch wenn, wie durch ein Glücksfall, diese beiden Anweisungen führen Sie in eine gehen, dieser thread kann verdrängt werden, bevor ~Schrank() gibt und andere threads können den Wert ändern, der von .fehlgeschlagen. Bottom line diese Systeme funktionieren nicht - es gibt keine Atomare test-and-set-Mechanismus für die Anwendung definierte Variablen.
Einige sagen, Destruktoren sollten niemals code, der scheitert. Alles andere ist ein schlechtes design. Ok, in Ordnung. Ich bin einfach nur neugierig zu sehen, was ein gutes design ist zu 100% Ausnahme-und thread-sicher in c++.