19

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;
    ...       
}

では、クリティカル セクションを例外で残しても問題ないのに、return ステートメントで残してはいけないのはなぜでしょうか。

4

1 に答える 1

20

いいえ、クリティカル セクションに例外を残すことはできません。この場合は文句を言いませんが、クリティカル セクションのブロックの周りに暗黙的に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、など) 内で例外がスローされた場合criticaltask同じコンストラクト内で実行を再開し、同じスレッドが例外をキャッチする必要があることが義務付けられています。この制限に違反すると、非準拠の OpenMP コードが発生し、そのようなすべての構造内に終了ハンドラーを含むブロックをg++挿入することによって、準拠が強制されます。try/catch

ステートメントが存在する場合のエラーに関してはreturn、OpenMP は C/C++ で構造化されたブロックを次のように定義します。

C/C++ の場合、上部に 1 つのエントリがあり、下部に 1 つの出口がある実行可能ステートメント (場合によっては複合)、または OpenMP コンストラクト。

また (すべての言語で):

構造化ブロックからの分岐点を終了点にすることはできません。

単にブロックの底から落ちるのとは異なり、明らかreturnにブロックの分岐を構成します。

于 2012-12-01T22:13:00.140 に答える