不,不允许有例外的关键部分。g++
在这种情况下不会抱怨,但它try/catch
会在关键部分的块周围默默地插入一个隐式。例如下面的代码:
#pragma omp critical (my_crit)
{
throw 3;
}
被 GCC 4.7 的 OpenMP 处理器降低为:
#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);
达到隐式内置的 catch-all 处理程序<<<eh_must_not_throw (terminate)>>>
会导致非常不优雅的终止:
terminate called after throwing an instance of 'int'
Abort trap: 6
try/catch
无论外部构造是否存在,都会插入隐式try/catch
,即异常永远不会离开该critical
部分。
parallel
OpenMP 标准规定,如果在大多数 OpenMP 构造( 、section
、master
、single
、for
、critical
、等)中引发异常,则task
必须在同一构造中恢复执行,并且同一线程必须捕获异常。违反此限制会导致不符合标准的 OpenMP 代码,并通过在所有此类构造中g++
插入try/catch
带有终止处理程序的块来简单地强制符合标准。
至于return
存在语句时的错误,OpenMP 将 C/C++ 中的结构化块定义为:
对于 C/C++,一个可执行语句,可能是复合语句,顶部有一个入口,底部有一个出口,或者是一个 OpenMP 结构。
还有(对于所有语言):
退出点不能是结构化块的分支。
显然return
构成了块的一个分支,不同于简单的块底部的下降。