No, non è OK lasciare una sezione critica con eccezioni. g++
non si lamenta in questo caso ma inserisce silenziosamente uno try/catch
implicito attorno al blocco della sezione critica. Ad esempio, il seguente codice:
#pragma omp critical (my_crit)
{
throw 3;
}
viene abbassato dal processore OpenMP di GCC 4.7 in:
#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);
Raggiungere l'implicita built-in catch-all gestore <<<eh_must_not_throw (terminate)>>>
risultati in cessazione piuttosto sgraziato:
terminate called after throwing an instance of 'int'
Abort trap: 6
L'implicito try/catch
viene inserito indipendentemente dalla presenza di un costrutto esterno try/catch
, ovvero l'ex l'inganno non lascerebbe mai la sezione critical
.
I mandati standard di OpenMP, che se viene generata un'eccezione nella maggior parte dei costrutti OpenMP (parallel
, section
, master
, single
, for
, critical
, task
, ecc), esecuzione deve riprendere entro lo stesso costrutto e che lo stesso filo deve prendere l'eccezione. La violazione di questa restrizione porta a codice OpenMP non conforme e g++
semplicemente impone la conformità inserendo blocchi try/catch
con gestori di terminazione all'interno di tutti questi costrutti.
quanto riguarda l'errore quando un'istruzione return
è presente, OpenMP definisce un blocco strcutured in C/C++ come:
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.
e anche (per tutte le lingue):
The point of exit cannot be a branch out of the structured block.
Ovviamente return
costituisce un ramo del blocco, diverso dalla semplice caduta del fondo del blocco.