Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Visual C++ unterstützt das Transportieren einer Ausnahme von einem Thread in einen anderen.Das Transportieren von Ausnahmen ermöglicht es Ihnen, eine Ausnahme in einem Thread abzufangen und anschließend werden die Ausnahme kann in einen anderen Thread ausgelöst werden soll.Beispielsweise können Sie diese Funktion verwenden, um einer Multithreadanwendung zu schreiben, in der der primäre Thread alle Ausnahmen behandelt, die von ihrer sekundären Threads ausgelöst werden.Ausnahmen zu transportieren ist vor allem nützlich, die Parallelprogrammierungs Entwickler von Bibliotheken oder - Systeme erstellen.Um das Transportieren von Ausnahmen zu implementieren, stellt Visual C++ exception_ptr den Typ und current_exception, rethrow_exceptioncopy_exception und Funktionen.
namespace std
{
typedef unspecified exception_ptr;
exception_ptr current_exception();
void rethrow_exception(exception_ptr p);
template<class E>
exception_ptr copy_exception(E e);
}
Parameter
Parameter |
Beschreibung |
|---|---|
unspecified |
Eine nicht angegebene interne Klasse, die verwendet wird, um den exception_ptr-Typ zu implementieren. |
p |
Ein exception_ptr-Objekt, das eine Ausnahme verwiesen wird. |
E |
Eine Klasse, die eine Ausnahme darstellt. |
e |
Eine Instanz der Parameter E-Klasse. |
Rückgabewert
Die current_exception-Funktion gibt ein exception_ptr-Objekt zurück, das die Ausnahme verwiesen wird, die gerade ausgeführt wird.Wenn keine Ausnahme noch ausgeführt wird, gibt die Funktion ein exception_ptr-Objekt zurück, das keiner Ausnahme zugeordnet ist.
Die copy_exception-Funktion gibt ein exception_ptr-Objekt zurück, das die Ausnahme verwiesen wird, die vom e-Parameter angegeben wird.
Hinweise
Szenario
Stellen Sie sich vor, dass Sie eine Anwendung erstellen möchten, die skalieren kann, um einen variablen Arbeitsaufwand zu behandeln.Um dieses Ziel zu erreichen, entwerfen Sie eine Multithreadanwendung in der eine ursprüngliche, primären Thread so viele sekundäre Threads erstellt sie um die Arbeit erledigen müssen.Die sekundären Threads helfen dem primären Thread, um Ressourcen zu verwalten, die Lädt und Durchsatz zu verbessern.Mit der Arbeit verteilt, führt die Multithreadanwendung besser als eine Singlethreade Anwendung aus.
Wenn jedoch ein sekundärer Thread eine Ausnahme auslöst, sollten Sie den primären Thread sie behandeln.Dies liegt daran, dass Sie die Anwendung Ausnahmen in einer konsistenten, einheitlichen Weise unabhängig von der Anzahl der sekundären Threads zu behandeln.
Lösung
Um das vorherige Szenario zu behandeln, unterstützt der C++-Standard das Transportieren einer Ausnahme zwischen Threads.Wenn ein sekundärer Thread eine Ausnahme auslöst, wird diese Ausnahme der aktuellen Ausnahme.Eine Analogie der realen Welt, wird die aktuelle Ausnahme in der Flug.Die aktuelle Ausnahme wird in der Flug aus der Zeit, die auf den Ausnahmehandler ausgelöst wird, den Erfassungen es zurück.
Der zweite Thread kann die aktuelle Ausnahme in einem catch-Block abfangen und ruft dann die current_exception-Funktion auf, um die Ausnahme in einem exception_ptr-Objekt gespeichert werden.Das exception_ptr-Objekt muss auf den sekundären Thread und den primären Thread verfügbar sein.Beispielsweise kann das exception_ptr-Objekt eine globale Variable sein, deren Zugriff durch einen Mutex gesteuert wird.transport Der Ausdruck , den eine Ausnahme besagt, dass eine Ausnahme in einem Thread auf ein Formular konvertiert werden kann, das durch einen anderen Thread zugegriffen werden kann.
Anschließend wird der primäre Thread die rethrow_exception-Funktion, die extrahiert und anschließend die Ausnahme vom exception_ptr-Objekt auslöst.Wenn die Ausnahme ausgelöst wird, wird die aktuelle Ausnahme in der primären Thread.Das heißt, wird die Ausnahme aus der primären Thread zu stammen.
Schließlich kann der primäre Thread die aktuelle Ausnahme in einem catch-Block abfangen und dann ein ASP.NET-Prozess wird oder in einer höheren Ebene Ausnahmehandler auslösen.Oder der primäre Thread kann die Ausnahme ignorieren und den Vorgang bis zum Ende ermöglichen.
Die meisten Anwendungen müssen Ausnahmen zwischen Threads weder transportieren.Allerdings ist diese Funktion in einem Parallel Computing-System nützlich, da das System beim Arbeiten mit sekundären Threads aufteilen kann, Prozessoren oder Kerne.In einer Parallel Computing-Umgebung kann ein einzelner, dedizierter Thread alle Ausnahmen von den sekundären Threads behandelt und kann ein konsistentes Modell der Ausnahmebehandlung in jeder Anwendung darstellen.
Weitere Informationen zu den C++-Normungsausschuss antrag, suchen Sie Belegnummer für das Internet N2179 Titel „, Sprachen-Unterstützung zum Transportieren von Ausnahmen zwischen Threads“.
Compileroptionen und Ausnahmebehandlungs-Modelle
Das Modell der Ausnahmebehandlung der Anwendung bestimmt, ob eine Ausnahme abfangen und transportieren kann.Visual C++ unterstützt drei Modelle, die Ausnahmen C++-Ausnahmen der strukturierten Ausnahmebehandlung (SEH) und Ausnahmen der Common Language Runtime (CLR) behandeln können.Verwenden Sie die /EH und /clr Modell der Ausnahmebehandlung mit Compileroptionen der Anwendung anzugeben.
Nur die folgende Kombination von Compileroptionen und Programmierung Anweisungen kann eine Ausnahme transportieren.Andere Kombinationen können entweder keine Ausnahmen abfangen oder Ausnahmen abfangen kann, kann jedoch nicht transportieren.
Die /EHa-Compileroption und die catchAnweisung können SEH und C++-Ausnahmen transportieren.
/EHa, und /EHsc/EHsCompileroptionen und catchAnweisung können C++-Ausnahmen transportieren.
Die /CLR oder /CLR:pure-Compileroption und die catchAnweisung können C++-Ausnahmen transportieren.Die /CLR-Compileroptionen bedeuten Angabe der Option /EHa .Beachten Sie, dass der Compiler nicht zum Transportieren von verwalteten Ausnahmen unterstützt.Dies liegt daran, dass verwaltete Ausnahmen, die von der System.Exception-Klasse abgeleitete Objekte handelt, die bereits Sie zwischen Threads verschieben können, indem Sie die Funktionen der allgemeinen languange Laufzeit verwenden.
SicherheitshinweisEs wird empfohlen, die /EHsc-Compileroption angeben und nur C++-Ausnahmen abfangen.Sie setzen sich aus einem Sicherheitsrisiko, wenn Sie die /EHa oder /CLR-Compileroption und eine catch-Anweisung mit einer Ellipse Ausnahmecatch(...)( Deklaration ) verwenden.Sie beabsichtigen, die wahrscheinlich catch-Anweisung verwenden, um mehrere spezifische Ausnahmen erfasst.Allerdings wird die catch(...)-Anweisung alle C++ und SEH, einschließlich der unerwarteten Ausnahmen aufgelistet, die schwer wiegend sein sollen.Wenn Sie eine unerwartete Ausnahme misshandeln oder ignorieren kann bösartiger Code diese Möglichkeit verwenden, die Sicherheit des Programms zu beeinträchtigen.
Verwendung
In den folgenden Abschnitten wird beschrieben, wie Ausnahmen, indem Sie den exception_ptrTyp und verwenden, current_exception, rethrow_exceptionund Funktionen copy_exception übertragen.
exception_ptr Typ
Verwenden Sie ein exception_ptr-Objekt, um die aktuelle Ausnahme oder eine Instanz einer vom Benutzer angegebene Ausnahme zu verweisen.In der Microsoft-Implementierung wird eine Ausnahme von einer EXCEPTION_RECORD Struktur dargestellt.Jedes exception_ptr Feld bezugs Ausnahme enthält ein Objekt, das eine Kopie der EXCEPTION_RECORD Struktur zeigt, die die Ausnahme darstellt.
Wenn Sie eine exception_ptr-Variable deklarieren, wird die Variable nicht mit einer beliebigen Ausnahme zugeordnet.Das heißt, ist sein bezugs Ausnahme im Feld NULL.Ein solches exception_ptr-Objekt wird als NULL exception_ptraufgerufen.
Verwenden Sie die current_exception oder copy_exception-Funktion, um eine Ausnahme zu einem exception_ptr-Objekt zugewiesen werden soll.Wenn eine Ausnahme von einer exception_ptr-Variablen zuweisen, zeigt das Feld bezugs Ausnahme der Variablen an eine Kopie der Ausnahme.Bei unzureichender Arbeitsspeicher vorhanden ist, den es, um die Ausnahme zu kopieren, zeigt das Feld bezugs Ausnahme zu einer Kopie einer std::bad_alloc Ausnahme.Wenn die current_exception oder copy_exception-Funktion die Ausnahme für einen anderen Grund nicht kopieren, kann die Funktion die terminate (CRT)-Funktion zum Überprüfen des aktuellen Prozesses beendet werden soll.
Trotz ihres Namens ist ein exception_ptr-Objekt nicht selbst ein Zeiger.Die Semantik Zeiger nicht befolgt und kann nicht mit den Operatoren der Zeiger zugriffs Member verwendet werden (->) oder eine Dereferenzierung (*).Das exception_ptr-Objekt verfügt über keine öffentlichen Datenmember oder Memberfunktionen.
Vergleiche:
Sie können dieselben (==) und NOT-gleichen (!=) Operatoren verwenden, um zwei exception_ptr-Objekte verglichen werden soll.Die Operatoren vergleichen nicht den Binärwert (Bitmuster) der EXCEPTION_RECORD Strukturen, die die Ausnahmen darstellen.Stattdessen Operatoren vergleichen die Adressen im Feld bezugs Ausnahme der exception_ptr-Objekten.Folglich den Vergleich NULL exception_ptr und der NULL-Wert als gleich.
current_exception Funktion
Rufen Sie die current_exception-Funktion in einem catch-Block an.Wenn eine Ausnahme in catch ist und der Flug Block die Ausnahme abfangen kann, gibt die current_exception-Funktion ein exception_ptr-Objekt zurück, das die Ausnahme verwiesen wird.Andernfalls gibt die Funktion NULL exception_ptr-Objekt zurück.
Details:
Die current_exception-Funktion zeichnet die Ausnahme aufgeführt, die im Flug ist unabhängig davon, ob die catch-Anweisung eine AusnahmeDeklaration-Anweisung angibt.
Der Destruktor für die aktuelle Ausnahme wird am Ende des catch-Blocks aufgerufen, wenn die Ausnahme erneut auslösen.Auch wenn Sie diecurrent_exception-Funktion im Destruktor aufrufen, gibt dieFunktion ein exception_ptr-Objekt zurück, das die aktuelle Ausnahme verwiesen wird.
Aufeinander folgende Aufrufe an die current_exception-Funktion geben exception_ptr-Objekten zurück, die unterschiedliche Kopien der aktuellen Ausnahme aus.Folglich vergleichen, während die Objekte ungleich, da sie unterschiedliche Kopien verweisen, obwohl die Kopien der gleichen Binärwert haben.
SEH Ausnahmen:
Wenn Sie die /EHa-Compileroption verwenden, können Sie SEH Ausnahme abfangen Block in C-Format ++ catch .Die current_exception-Funktion gibt ein Objekt zurück, das exception_ptr SEH Ausnahme verwiesen wird.Und die rethrow_exception-Funktion löst SEH Ausnahme aus, wenn Sie sie mit demtransportierten exception_ptr-Objekt als Argument aufrufen.
Die current_exceptionexception_ptr-Funktion gibt NULL zurück, wenn es in __finally SEH Beendigungshandler, ein __except Ausnahmehandler oder der __except Filterausdruck aufgerufen werden.
Eine transportierte Ausnahme unterstützt keine geschachtelte Ausnahmen.Eine geschachtelte Ausnahme tritt auf, wenn eine andere Ausnahme ausgelöst wird, während eine Ausnahme behandelt wird.Wenn Sie eine geschachtelte Ausnahme abfangen, zeigt der EXCEPTION_RECORD.ExceptionRecord Datenmember einer Kette von EXCEPTION_RECORD Strukturen, die die zugeordneten Ausnahmen beschreiben.Die current_exception-Funktion unterstützt keine geschachtelte Ausnahmen, da sie ein exception_ptr-Objekt zurückgibt, dessen ExceptionRecord Datenmember auf null festgelegt wird, ausgecheckt.
Wenn Sie SEH Ausnahme abfangen, müssen Sie den Speicherplatz, der zum Verwalten von einem Zeiger EXCEPTION_RECORD.ExceptionInformation Datenmember im Array verwiesen wird.Stellen Sie sicher, dass der Arbeitsspeicher während der Lebensdauer des entsprechenden exception_ptr-Objekts gültig ist und dass der Arbeitsspeicher freigegeben wird, wenn das exception_ptr-Objekt gelöscht wird.
Sie können Funktionen zur Übersetzung für die strukturierte Ausnahme (SE) zusammen mit der Funktion für ausnahme Transport verwenden.Wenn SEH Ausnahme Ausnahme in C-Format ++ übersetzt wird, gibt die Funktion current_exceptionexception_ptr zurück, die die übersetzte Ausnahme anstelle der Vorlage SEH Ausnahme verwiesen wird.Die rethrow_exception-Funktion löst daraufhin die übersetzte keine Ausnahme die ursprüngliche Ausnahme aus.Weitere Informationen zu SE-Übersetzer Funktionen finden Sie unter _set_se_translator.
rethrow_exception Funktion
Nachdem Sie eine abgefangene Ausnahme in einem exception_ptr-Objekt speichern, kann der primäre Thread das Objekt verarbeiten.Im primären Thread rufen Sie die rethrow_exception-Funktion zusammen mit dem exception_ptr-Objekt als Argument an.Die rethrow_exception-Funktion extrahiert die Ausnahme vom exception_ptr-Objekt und anschließend wird die Ausnahme im Kontext des primären Threads aus.Wenn der p-Parameter der Funktion rethrow_exceptionexception_ptrNULL ist, wird die Funktion std::bad_exceptionaus.
Der extrahierte Ausnahme ist jetzt die aktuelle Ausnahme im primären Thread, und Sie können diese verarbeiten, während Sie jede andere Ausnahme wurden.Wenn Sie die Ausnahme abfangen, können Sie ihn sofort verarbeiten oder eine throw-Anweisung verwenden, um sie zu einer höheren Ebene Ausnahmehandler zu senden.Andernfalls müssen Sie nichts, und lassen Sie den Standardnamen ausnahmehandler System den Prozess beenden.
copy_exception Funktion
Die copy_exception-Funktion akzeptiert eine Instanz einer Klasse als Argument und gibt dann exception_ptr zurück, das die Instanz verweist.Normalerweise geben Sie ein Ausnahmeklasse-Objekt als Argument an die copy_exception-Funktion auf, obwohl jedes Klassenobjekt das Argument sein kann.
Die copy_exception-Funktion aufzurufen ist zum Auslösen einer Ausnahme in C++ zum Abfangen sie in einem catch-Block, und die current_exception-Funktion aufrufen, um dann exception_ptr ein Objekt zurückgegeben, das die Ausnahme verwiesen wird.Die Microsoft-Implementierung der copy_exception-Funktion ist effizienter als einer Ausnahme Auslösen von Ereignissen und anschließend abfangend.
Eine Anwendung in der Regel nicht erforderlich copy_exception die Funktion, und wir entmutigen ihre Verwendung.
Beispiel
Im folgenden Beispiel C++-ausnahme eine standardmäßige übertragen und von einem Thread eine benutzerdefinierte C++-Ausnahmebehandlung zu einem anderen.
// transport_exception.cpp
// compile with: /EHsc /MD
#include <windows.h>
#include <stdio.h>
#include <exception>
#include <stdexcept>
using namespace std;
// Define thread-specific information.
#define THREADCOUNT 2
exception_ptr aException[THREADCOUNT];
int aArg[THREADCOUNT];
DWORD WINAPI ThrowExceptions( LPVOID );
// Specify a user-defined, custom exception.
// As a best practice, derive your exception
// directly or indirectly from std::exception.
class myException : public std::exception {
};
int main()
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
// Create secondary threads.
for( int i=0; i < THREADCOUNT; i++ )
{
aArg[i] = i;
aThread[i] = CreateThread(
NULL, // Default security attributes.
0, // Default stack size.
(LPTHREAD_START_ROUTINE) ThrowExceptions,
(LPVOID) &aArg[i], // Thread function argument.
0, // Default creation flags.
&ThreadID); // Receives thread identifier.
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return -1;
}
}
// Wait for all threads to terminate.
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread handles.
for( int i=0; i < THREADCOUNT; i++ ) {
CloseHandle(aThread[i]);
}
// Rethrow and catch the transported exceptions.
for ( int i = 0; i < THREADCOUNT; i++ ) {
try {
if (aException[i] == NULL) {
printf("exception_ptr %d: No exception was transported.\n", i);
}
else {
rethrow_exception( aException[i] );
}
}
catch( const invalid_argument & ) {
printf("exception_ptr %d: Caught an invalid_argument exception.\n", i);
}
catch( const myException & ) {
printf("exception_ptr %d: Caught a myException exception.\n", i);
}
}
}
// Each thread throws an exception depending on its thread
// function argument, and then ends.
DWORD WINAPI ThrowExceptions( LPVOID lpParam )
{
int x = *((int*)lpParam);
if (x == 0) {
try {
// Standard C++ exception.
// This example explicitly throws invalid_argument exception.
// In practice, your application performs an operation that
// implicitly throws an exception.
throw invalid_argument("A C++ exception.");
}
catch ( const invalid_argument & ) {
aException[x] = current_exception();
}
}
else {
// User-defined exception.
aException[x] = copy_exception( myException() );
}
return TRUE;
}
Anforderungen
Header: <exception>
Siehe auch
Referenz
Ausnahmebehandlung in Visual C++
EXCEPTION_RECORD-Struktur
Handler-Syntax