web-dev-qa-db-ja.com

アクティブな例外なしで呼び出されるC ++終了

スレッドでC++エラーが発生しています:

terminate called without an active exception
Aborted

コードは次のとおりです。

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

template<typename TYPE>
class blocking_stream
{
public:
    blocking_stream(size_t max_buffer_size_)
        :   max_buffer_size(max_buffer_size_)   
    {
    }

    //Push data into the buffer
    blocking_stream &operator<<(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx); 
        while(buffer.size()>=max_buffer_size)
            stop_if_full.wait(mtx_lock);

        buffer.Push(std::move(other));

        mtx_lock.unlock();
        stop_if_empty.notify_one();
        return *this;
    }
    //POP data out of the buffer 
    blocking_stream &operator>>(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx);
        while(buffer.empty())
            stop_if_empty.wait(mtx_lock);

        other.swap(buffer.front()); 
        buffer.pop();

        mtx_lock.unlock();
        stop_if_full.notify_one();
        return *this;
    }

private:
    size_t max_buffer_size;
    std::queue<TYPE> buffer;
    std::mutex mtx;
    std::condition_variable stop_if_empty,
                            stop_if_full;
    bool eof;   
};

この例を中心にコードをモデル化しました: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

私は何を間違えていますか?エラーを修正するにはどうすればよいですか?

66
111111

スレッドオブジェクトが範囲外になり、結合可能な状態になると、プログラムは終了します。標準委員会には、結合可能なスレッドのデストラクタのための2つのオプションがありました。静かに結合できますが、スレッドがスタックしていると、結合が戻らない可能性があります。または、スレッドをデタッチできます(デタッチされたスレッドは結合できません)。ただし、デタッチされたスレッドは、プログラムの最後まで存続し、リソースのリリースを台無しにする可能性があるため、非常に注意が必要です。したがって、プログラムを終了したくない場合は、必ずすべてのスレッドに参加(または分離)してください。

92

そのエラーを再現する方法:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  return 0;
}

コンパイルして実行します:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
terminate called without an active exception
Aborted (core dumped)

スレッドに参加またはデタッチしなかったため、このエラーが発生します。

それを修正する1つの方法は、このようにスレッドに参加します:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  t1.join();
  return 0;
}

次に、コンパイルして実行します。

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

それを修正する他の方法は、このようにデタッチします:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() 
{ 
     {

        std::thread t1(task1, "hello"); 
        t1.detach();

     } //thread handle is destroyed here, as goes out of scope!

     usleep(1000000); //wait so that hello can be printed.
}

コンパイルして実行します:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

C++スレッドのデタッチとC++スレッドへの参加について読んでください。

37
Eric Leschinski

Eric LeschinskiとBartosz Milewskiはすでに答えを出しています。ここでは、より初心者に優しい方法でそれを提示しようとします。

スコープ内でスレッドが開始されると(スレッド自体がスレッドで実行されている場合)、スレッドがスコープ外になる前に、次のいずれかが明示的に発生することを明示的に確認する必要があります。

  • ランタイムは、そのスレッドの実行が終了した後にのみスコープを終了します。これは、そのスレッドと結合することにより実現されます。言語に注意してください、それはそのスレッドと結合する外側のスコープです。
  • ランタイムは、それ自体で実行するスレッドを残します。そのため、このスレッドの実行が終了したかどうかにかかわらず、プログラムはスコープを終了します。このスレッドは、それ自体で実行および終了します。これは、スレッドを切り離すことで実現されます。これにより、たとえば、スレッドがその外部スコープ内の変数を参照している場合に問題が発生する可能性があります。

スレッドが結合または切り離されるまでに、実行が十分に終了していることに注意してください。それでも、2つの操作のいずれかを明示的に実行する必要があります。

16
haripkannan

プログラムが停止する限り、スレッドの切り離しまたは結合を行わないと、このエラーが発生します。スレッドを切り離して参加せずに、スレッドを作成した後に無限ループを与える必要があります。

int main(){

std::thread t(thread,1);

while(1){}

//t.detach();
return 0;}

また、スリープまたはループした後、スレッドをデタッチまたは結合できることも興味深いです。この方法でも、このエラーは発生しません。

以下の例は、3番目のスレッドがメインダイの前にジョブを実行できないことも示しています。ただし、コード内のどこかでデタッチする限り、このエラーは発生しません。 3番目のスレッドは8秒間スリープしますが、メインは5秒で終了します。

void thread(int n) {std::this_thread::sleep_for (std::chrono::seconds(n));}

int main() {
std::cout << "Start main\n";
std::thread t(thread,1);
std::thread t2(thread,3);
std::thread t3(thread,8);
sleep(5);

t.detach();
t2.detach();
t3.detach();
return 0;}
0
user2908225