Nein, es ist nicht in Ordnung, einen kritischen Abschnitt mit Ausnahmen zu verlassen. g++
beschwert sich in diesem Fall nicht, aber es fügt unbemerkt einen impliziten try/catch
um den Block des kritischen Abschnitts ein. Beispielsweise den folgenden Code:
#pragma omp critical (my_crit)
{
throw 3;
}
wird durch den OpenMP Prozessor von GCC 4.7 in abgesenkt:
#pragma omp critical (my_crit)
__builtin_GOMP_critical_name_start (&.gomp_critical_user_my_crit);
try
{
D.20639 = __cxa_allocate_exception (4);
try
{
MEM[(int *)D.20639] = 3;
}
catch
{
__cxa_free_exception (D.20639);
}
__cxa_throw (D.20639, &_ZTIi, 0B);
}
catch
{
<<<eh_must_not_throw (terminate)>>>
}
__builtin_GOMP_critical_name_end (&.gomp_critical_user_my_crit);
Erreichen der impliziten Einbau-Catch-All-Handler <<<eh_must_not_throw (terminate)>>>
Ergebnisse in ganz ungraceful Beendigung:
Die implizite try/catch
wird eingefügt, unabhängig von der Anwesenheit eines äußeren try/catch
Konstrukts, dh der ex ception würde nie den critical
Abschnitt verlassen.
Die OpenMP Standard Aufträge, dass, wenn eine Ausnahme in den meisten Konstrukten OpenMP geworfen wird (parallel
, section
, master
, single
, for
, critical
, task
, etc.), wird die Ausführung innerhalb des gleichen Konstrukts, und dass demselben Thread wieder aufnehmen müssen muss die Ausnahme abfangen. Ein Verstoß gegen diese Einschränkung führt zu einem nicht-konformen OpenMP-Code und g++
erzwingt einfach die Konformität, indem er try/catch
Blöcke mit Beendigungshandlern in alle diese Konstrukte einfügt.
Wie für den Fehler, wenn eine return
Anweisung vorhanden ist, definiert OpenMP einen strcutured Block in C/C++ als:
For C/C++, an executable statement, possibly compound, with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
und auch (für alle Sprachen):
The point of exit cannot be a branch out of the structured block.
Offensichtlich return
stellt einen Zweig des Blocks dar, der sich vom einfachen Fallen des unteren Blocks unterscheidet.