Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

terminate called recursively

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.

like image 459
Shamdor Avatar asked Sep 10 '12 08:09

Shamdor


2 Answers

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
like image 64
Jayhello Avatar answered Oct 30 '22 10:10

Jayhello


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".

like image 43
Some programmer dude Avatar answered Oct 30 '22 10:10

Some programmer dude