スレッドで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
私は何を間違えていますか?エラーを修正するにはどうすればよいですか?
スレッドオブジェクトが範囲外になり、結合可能な状態になると、プログラムは終了します。標準委員会には、結合可能なスレッドのデストラクタのための2つのオプションがありました。静かに結合できますが、スレッドがスタックしていると、結合が戻らない可能性があります。または、スレッドをデタッチできます(デタッチされたスレッドは結合できません)。ただし、デタッチされたスレッドは、プログラムの最後まで存続し、リソースのリリースを台無しにする可能性があるため、非常に注意が必要です。したがって、プログラムを終了したくない場合は、必ずすべてのスレッドに参加(または分離)してください。
そのエラーを再現する方法:
#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++スレッドへの参加について読んでください。
Eric LeschinskiとBartosz Milewskiはすでに答えを出しています。ここでは、より初心者に優しい方法でそれを提示しようとします。
スコープ内でスレッドが開始されると(スレッド自体がスレッドで実行されている場合)、スレッドがスコープ外になる前に、次のいずれかが明示的に発生することを明示的に確認する必要があります。
スレッドが結合または切り離されるまでに、実行が十分に終了していることに注意してください。それでも、2つの操作のいずれかを明示的に実行する必要があります。
プログラムが停止する限り、スレッドの切り離しまたは結合を行わないと、このエラーが発生します。スレッドを切り離して参加せずに、スレッドを作成した後に無限ループを与える必要があります。
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;}