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

Leo*_*ura 16 c++ openmp

我想知道在OMP关键部分中抛出C++异常是否安全.

#pragma omp critical (my_critical_section)
{
    ...
    throw my_exception("failed")
    ...       
}
Run Code Online (Sandbox Code Playgroud)

g ++不抱怨.我很困惑,因为它抱怨return关键部分内的陈述.它返回错误:invalid exit from OpenMP structured block我写的时候

#pragma omp critical (my_critical_section)
{
    ...
    return;
    ...       
}
Run Code Online (Sandbox Code Playgroud)

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

Hri*_*iev 18

不,离开具有例外的关键部分是不可行的.g++在这种情况下不会抱怨,但它会默默地try/catch在临界区的块周围插入一个隐含的内容.例如,以下代码:

#pragma omp critical (my_crit)
{
   throw 3;
}
Run Code Online (Sandbox Code Playgroud)

被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);
Run Code Online (Sandbox Code Playgroud)

到达隐式内置catch-all处理程序会<<<eh_must_not_throw (terminate)>>>导致非常不合适的终止:

terminate called after throwing an instance of 'int'
Abort trap: 6
Run Code Online (Sandbox Code Playgroud)

try/catch无论是否存在外部try/catch构造,都会插入隐式,即异常永远不会离开该critical部分.

OpenMP标准的任务,如果有异常最OpenMP构造(内抛出parallel,section,master,single,for,critical,task,等),必须执行同一构造内恢复,并且在同一个线程必须捕获该异常.违反此限制会导致不符合规范的OpenMP代码,并g++通过try/catch在所有此类构造中插入具有终止处理程序的块来简单地强制执行一致性.

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

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

还(适用于所有语言):

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

显然return构成了块的一个分支,不同于块的底部的简单下降.