在omp关键部分中抛出C ++异常

时间:2012-12-01 20:05:34

标签: c++ openmp

我想知道在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;
    ...       
}

那么,为什么离开临界区有一个例外是可以的,但确定留下一个返回语句?

1 个答案:

答案 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构造中抛出异常(parallelsectionmastersinglefor,{ {1}},critical等),执行必须在同一个构造内恢复,并且同一个线程必须捕获异常。违反此限制会导致不符合要求的OpenMP代码,task只需在所有此类构造中插入带有终止处理程序的g++块,即可强制执行一致性。

对于存在try/catch语句时的错误,OpenMP在C / C ++中定义了一个strcutured块:

  

对于C / C ++,一个可执行语句,可能是复合语句,顶部有一个条目,底部有一个出口,或者是OpenMP构造。

以及(适用于所有语言):

  

退出点不能是结构化块的分支。

显然return构成了区块的一个分支,不同于简单地从区块底部掉落。