我想知道在OMP关键部分中抛出C ++异常是否安全。
#pragma omp critical (my_critical_section)
{
...
throw my_exception("failed")
...
}
g ++没有抱怨。我感到困惑,因为它抱怨了关键部分内的return
个陈述。当我写
invalid exit from OpenMP structured block
#pragma omp critical (my_critical_section)
{
...
return;
...
}
那么,为什么离开临界区有一个例外是可以的,但不确定留下一个返回语句?
答案 0 :(得分:17)
不,离开一个有例外的关键部分是不行的。 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
部分。
OpenMP标准规定,如果在大多数OpenMP构造中抛出异常(parallel
,section
,master
,single
,for
,{ {1}},critical
等),执行必须在同一个构造内恢复,并且同一个线程必须捕获异常。违反此限制会导致不符合要求的OpenMP代码,task
只需在所有此类构造中插入带有终止处理程序的g++
块,即可强制执行一致性。
对于存在try/catch
语句时的错误,OpenMP在C / C ++中定义了一个strcutured块:
对于C / C ++,一个可执行语句,可能是复合语句,顶部有一个条目,底部有一个出口,或者是OpenMP构造。
以及(适用于所有语言):
退出点不能是结构化块的分支。
显然return
构成了区块的一个分支,不同于简单地从区块底部掉落。