26

This Questionに従って、スレッドを使用してユーザー入力で関数を終了しています。私のコードは次のようになります。

bool stopper = false;
thread stopThread(userStop, &stopper);      // start thread looking for user input
for(int i = 0; i < 1000; i++) {
    if(stopper) { break; }                  // break if desired
    // Do stuff
}
return 0;

どこ、

userStop(bool *st) {
    char chChar = getchar();
    if(chChar == '\n') {
        *st = true;
    }
}

これを実行すると、エラーが発生しますterminate called without an active exception。これらの質問に基づいて:アクティブな例外なしで呼び出されたスレッドの終了、アクティブな例外なしで呼び出されたC++ の終了。スレッドに再び「参加」していないため、そのように見えます。

問題は、スレッドに「参加」したくないということです。ユーザーは終了するために入力を提供する必要userStop()があるためですが、forループが壊れる場合にのみユーザーに入力を提供してもらいたいです(必ずしもそうではありません)。

ありがとう!

4

3 に答える 3

39

発生している問題はstopThread、スタックの範囲外に出た結果です。C++ 標準では、これについて次のように述べています。

30.3.1.3 スレッドデストラクタ [thread.thread.destr]

〜スレッド();

joinable()の場合はterminate()、それ以外の場合は効果なし。[注:デストラクタでjoinable()スレッドを暗黙的にデタッチまたは結合すると、例外が発生した場合にのみ発生する正確性 (デタッチの場合) またはパフォーマンス (結合の場合) バグのデバッグが困難になる可能性があります。したがって、プログラマは、スレッドがまだ結合可能である間はデストラクタが実行されないようにする必要があります。—エンドノート]

join()これが意味することは、最初にまたはを呼び出すことなく、スレッドをスコープ外に出してはならないということですdetach()

あなたが説明した方法では、スレッドが参加せずにスコープ外になり、アプリケーションの実行中にスレッドが引き続き実行されるようにする必要があります。それには への呼び出しが必要detach()です。そこから、少しの知恵しか提供できません...

  • そのスレッドは、それ自身の存続期間に対して完全に責任を持つようになりました。独自に返されない場合は、永久に (プロセスが終了するまで) 実行されます。

  • おそらくcinまたはのようなものから、ユーザー入力を取得していますgetch()。これらが複数のスレッドからアクセスされる場合、ライブラリの実装に競合状態がないという保証はあまりありません。軽く踏む。

于 2012-12-22T06:45:31.173 に答える
4

標準の入力スレッドでは、入力から非同期で読み取る必要があります。そして、読み取りを停止する要求と新しい入力の両方で目を覚まします。

結合せずにスレッドを終了することは、合理的なことではありません。ですから、あなたができる必要があるのは、「よスレッド、今すぐ終了する」と言うことです。そうすれば、結合がすぐに終了することを期待できます。これは、場合によっては、2段階のハンドシェイク(「yothread、finish up」、続いて「ok ok、なんとかクリーンアップして、今すぐ参加する」)を介することもできます。

ループ1000は本当にばかげているように見えることに注意してください。ユーザー入力のタイムアウトは、通常、実際の時間の経過、またはユーザー入力を役に立たなくするその他のイベントの発生に基づいている必要があります。

于 2012-12-22T02:26:23.960 に答える
1

スレッドを終了することは悪い考えです-スレッドを正常に終了させる必要があります。スレッドを終了した場合、getch()関数内のコードが予期せず終了することになります。そのコードがデータ構造の管理、メモリの割り当てまたは解放、または完了まで実行する必要のあるその他の作業を行っている最中だった場合はどうなりますか?何かを無効な状態のままにしてしまうことになり、その無効な状態が実行されると最終的にクラッシュします。

于 2012-12-22T02:15:47.940 に答える