11

http://en.cppreference.com/w/cpp/error/terminateに記載されているように、terminateを呼び出す理由はたくさんあります。ほぼ同時に、これらの理由のいくつかが2つのスレッドで発生する場合を想像できます。

Q1設定された終了関数をstd::set_terminate同時に2回以上呼び出すことはできますか?同時に、最初の呼び出しが終了する前に2番目の呼び出しが開始されることを意味します。

  Thread1   Thread2
    |          |
    _          |
    t          |
    e          |
    r          |
    m          |
    i          _
    n          t
    a          e
    t          r
    e          m
    -          ?

Q2 Q1 == YESの場合、最初の終了が終了するとどうなりますか。std :: abortで終了した場合、プログラムは終了すると思いますが、ユーザーが提供した終了がプログラムを中止しない場合はどうなりますか?

Q3終了関数は、std::set_terminateこの終了呼び出しの原因となったスレッドのコンテキストで呼び出されて設定されますか?

4

1 に答える 1

7

Q1

はい、std::terminate同時に呼び出すことができます。

Q2

terminate_handler標準では、「呼び出し元に戻らずにプログラムの実行を終了」しないことは未定義の動作であるとされています。私が精通している実装ではterminate_handler、通常または例外的に戻る試みabort()が呼び出されます。

Q3

によって設定される関数std::terminateはグローバルであり、スレッドローカルではありません。したがって、あるスレッドが別のスレッドに影響を与える可能性があります。

C ++ 98/03では、キャッチされなかった例外のために呼び出さterminate_handlerれたときに使用されるのは、実際に呼び出されterminateたときに有効なものではなく、例外がスローされたときに有効だったものterminateです(通常は同じですが)。

terminateC ++ 11ではこれが変更され、標準では、使用されるハンドラーは、呼び出された時点で使用されているハンドラーであると規定されています。この変更は誤って行われたものであり、将来のドラフトで修正される可能性があります。この問題を追跡するLWGの問題は次のとおりです。

http://cplusplus.github.com/LWG/lwg-active.html#2111

アップデート

カンザス州レネクサで開催された2015年春の会議で、LWGは既存の動作を標準化することを決定し、スタックの巻き戻し中に呼び出されたterminate_handler場合に新しい動作が有効になるタイミングを指定しませんでした。set_terminateつまり、実装はC++98/03ルールまたはC++11ルールのいずれかに従うことができます。

コードを移植可能にするために、を設定する必要がある場合はterminate_handler、プログラムの起動時に例外がスローされる前に設定し、その後に呼び出す習慣を付けないでくださいset_terminate

于 2012-10-27T21:56:29.923 に答える