[解決済み] main()が終了したとき、デタッチド・スレッドはどうなるのでしょうか?
質問
を始めると仮定します。
std::thread
で、次に
detach()
を含むので、スレッドが実行され続けます。
std::thread
を表現していたものが、スコープ外に出てしまったのです。
さらに、プログラムが切り離されたスレッドに参加するための信頼できるプロトコルを持っていないと仮定します。
1
のとき、切り離されたスレッドはまだ実行されています。
main()
が終了します。
標準規格(正確には N3797 C++14 ドラフト)の 1.10 と 30.3 のいずれにも適切な文言が含まれておらず、どのようなことが起こるべきかを記述したものが見当たりません。
1 なぜなら、参加するためにどのようなプロトコルを発明するにしても、シグナリング部分はスレッドがまだ動作している間に行われなければならず、OSスケジューラはシグナリングが行われた直後にスレッドを1時間スリープさせることを決定し、受信側がスレッドが実際に終了したことを確実に検出する方法はないからです。
を使い切った場合
main()
は未定義な動作です。
任意の
の使用
std::thread::detach()
は、メインスレッドが決して終了しない限り、未定義の動作です。
2
.
を使い果たすと
main()
デタッチド・スレッドが動作している状態では
定義された
の効果があります。という質問があります。
どこ
(は、(その中の
C++標準
POSIXでもOSのドキュメントでもなく...)で定義されている効果です。
2
切り離されたスレッドを結合することはできません(
std::thread::join()
). あなたは
できる
からのfutureを経由して)分離されたスレッドからの結果を待ちます。
std::packaged_task
しかし、これは
の実行を終了しています。
. 実際、スレッドの最初の自動オブジェクトのデストラクタにシグナリングの部分を入れない限り、そこに
意志
を実行するコード(デストラクタ)が存在します。
後
信号のコード。もしOSがメインスレッドが結果を消費し、デタッチドスレッドが前記デストラクタの実行を終える前に終了するようスケジュールした場合、何が起こるか^Wisは定義されていますか?
解決方法は?
元の質問に対する答えは、「切り離されたスレッドは、次のような場合にどうなるのか」というものです。
main()
exits" です。
他のスレッドの(自動|thread_local)変数や静的オブジェクトに触れない限り、 (標準では停止しているとは書かれていないので)それは走り続け、 それはうまく定義されています。
これは、スレッドマネージャーを静的オブジェクトとして許可しているようです(註 [基本.開始.項]/4 にはそのように書かれています。ポインタをくれた @dyp に感謝します)。
静的オブジェクトの破壊が終了すると、シグナルハンドラで許可されたコードのみが実行できる体制に入るため、問題が発生します (
[基本.開始.項]/1、第1文
). C++の標準ライブラリのうち、それだけが
<atomic>
ライブラリ(
[サポート.ランタイム]/9、第2文
). 特に、一般的に
を除きます。
condition_variable
(の一部ではないので、シグナルハンドラで使用するために保存されるかどうかは実装で決まります)。
<atomic>
).
この時点でスタックを解放していなければ、未定義の動作を回避する方法はわかりません。
2つ目の質問「切り離されたスレッドを再び結合することは可能か」に対する答えは、次のとおりです。
はい。
*_at_thread_exit
関数群 (
notify_all_at_thread_exit()
,
std::promise::set_value_at_thread_exit()
, ...).
質問の脚注[2]にあるように、条件変数やセマフォやアトミックカウンターをシグナリングすることは、(その実行の終了を保証するという意味で)切り離されたスレッドを結合するには十分ではありません。
ハッシュハップンビフォー
の後に実行されるコードが多くなるため、待機中のスレッドがそのシグナルを受け取ることができない。
notify_all()
特に、自動的なオブジェクトやスレッドローカルなオブジェクトのデストラクタがそうである。
スレッドが最後に行うこととしてシグナルを実行する (
後
自動生成オブジェクトとスレッドローカルオブジェクトのデストラクタ
ハプニング
) は、どのような
_at_thread_exit
は、そのために設計された関数群です。
したがって、標準が要求する以上の実装保証がない場合に未定義の動作を避けるためには、切り離されたスレッドを(手動で)
_at_thread_exit
関数がシグナル伝達を行う
または
切り離されたスレッドに実行させる
のみ
のコードも、シグナルハンドラとしては安全でしょう。
関連
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] プロセスとスレッドの違いは何ですか?
-
[解決済み] std::move()とは何ですか?また、どのような場合に使用するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない