As far as I know, terminate()
is called when there is some problem with exception handling(usually it's just not caught).
What I got is just one error line terminate called recursively
.
After googling for some time I found a lot of examples of
terminate called after throwing an instance of ... terminate called recursively
But it's not my case. As I don't have this hint about the exception type, I'm wondering what does this terminate called recursively
mean by itself.
Sorry I can't provide the code, so any guess will be helpful. I'm compiling with g++ 4.5.2 under Ubuntu 11.04.
Thanks a lot, Alex.
I have encounter this question, it's maybe the error
of your function in thread pool
or thread
.
Let's recur the terminate called recursively
exception
.
I am writing a thread pool with c++11
, here is my code:
// blocking queue
template<typename T>
class SafeQueue{
public:
bool pop(T& value){
std::lock_guard<std::mutex> lock(mtx_);
if(queue_.empty())
return false;
value = queue_.front();
queue_.pop_front();
return true;
}
void push(T&& value){
std::lock_guard<std::mutex> lock(mtx_);
queue_.push_back(std::move(value));
}
bool empty(){
std::lock_guard<std::mutex> lock(mtx_);
return queue_.empty();
}
private:
std::mutex mtx_;
std::list<T> queue_;
};
typedef std::function<void()> Task;
typedef SafeQueue<Task> Tasks;
class ThreadPool{
public:
ThreadPool(uint32_t nums=5, bool start=false);
~ThreadPool();
void start();
void addTask(Task&& task);
void join();
void exit();
size_t getThreadNum(){return threadNums_;}
private:
Tasks tasks_;
std::vector<std::thread> threads_;
size_t threadNums_;
bool stop_;
};
ThreadPool::ThreadPool(uint32_t nums, bool start):
threadNums_(nums), stop_(false)
{
if(start)
this->start();
}
ThreadPool::~ThreadPool(){
stop_ = true;
}
void ThreadPool::start(){
auto lb_thread_fun = [this](){
while (!stop_){
Task task;
tasks_.pop(task);
// error from here, task maybe empty.
task();
}
};
for (int i = 0; i < threadNums_; ++i) {
threads_.push_back(std::thread(lb_thread_fun));
}
}
void ThreadPool::addTask(Task&& task){
tasks_.push(std::move(task));
}
void ThreadPool::join(){
for (auto& th:threads_) {
th.join();
}
}
void ThreadPool::exit(){
stop_ = true;
}
Test code as below:
#include "my_threadpool.h"
#include <iostream>
using std::cout;
using std::endl;
auto lb_dummy_dw = [](const std::string& url){
cout<<"start downloading: "<<url<<endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
cout<<"downloading success !!!!"<<url<<endl;
};
auto lb_dummy_sql = [](int id, const std::string& name){
cout<<"start select from db, id:" << id << ", name: "<<name<<endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
cout<<"select db success !!!!"<<endl;
};
void test_thread_pool(){
cout<<"create thread pool with 5 thread"<<endl;
xy::ThreadPool tp(5);
cout<<"add 3 * 2 task to thread pool"<<endl;
for (int i = 0; i < 3; ++i) {
tp.addTask(std::bind(lb_dummy_dw, "ww.xxx.com"));
tp.addTask(std::bind(lb_dummy_sql, i, "xy" + std::to_string(i)));
}
cout<<"start thread pool"<<endl;
tp.start();
tp.join();
}
int main(){
test_thread_pool();
return 0;
}
When you run the above code, you may get the below output:
create thread pool with 5 thread
add 3 * 2 task to thread pool
start thread pool
start downloading: ww.xxx.com
start select from db, id:0, name: xy0
start downloading: ww.xxx.com
start select from db, id:1, name: xy1
start downloading: ww.xxx.com
downloading success !!!!ww.xxx.com
start select from db, id:2, name: xy2
downloading success !!!!ww.xxx.com
downloading success !!!!ww.xxx.com
terminate called recursively
terminate called after throwing an instance of 'std::bad_function_call'
what():
You can see, it got terminate called recursively
exception. Because, in the function start
, the variable task
maybe empty, so each thread in the thread pool
throw bad_function_call
exception.
void ThreadPool::start(){
auto lb_thread_fun = [this](){
while (!stop_){
Task task;
tasks_.pop(task);
// error from here, task maybe empty.
task();
}
};
for (int i = 0; i < threadNums_; ++i) {
threads_.push_back(std::thread(lb_thread_fun));
}
}
Task empty test code as below:
void test_task(){
Task task;
try{
task();
}catch (std::exception& e){
cout<<"running task, with exception..."<<e.what()<<endl;
return;
}
cout<<"ending task, without error"<<endl;
}
Output as below:
running task, with exception...bad_function_call
Could be that some code throws an exception you don't catch, which means terminate
will be called. Terminating the program means that object destructors might be called, and if there is an exception in one of them then terminate
will be called "recursively".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With