Anand Kulkarni
Anand Kulkarni

Reputation: 435

SIGABRT and thread related exception but works fine during debug

The below code blows up during run time but works fine during debug. I cant understand why. I am joining the thread in destructor as required.

Could some one help ?

surprisingly the code works fine during debug.

Tried couple of times in debug and every time seems fine.

#include<iostream>
#include<string>
#include<thread>
#include<memory>

using namespace std;

template<typename T> class Runnable
{
    private:
        std::thread t;

        void runImpl()
        {
            static_cast<T*>(this)->run();
        }

    public:
        virtual void run() = 0;
        void start()
        {
            this->t = std::thread(&Runnable::runImpl, this);
        }

        ~Runnable()
        {
            std::cout << "I am in the destructor of the base class" << std::endl;
            if(t.joinable())
            {
                std::cout << "joinable" << std::endl;
                t.join();
            }
            else
                std::cout << "not joinable" << std::endl;
        }
};

class HelloWorld : public Runnable<HelloWorld>
{
    public:
        void run()
        {
            std::cout <<  "I am in thread id = " << std::this_thread::get_id()  << " and the message is : HelloWorld How are you" << std::endl;
        }
};

int main(int argc, char* argv[])
{
    std::cout << "I am in the main thread id = " << std::this_thread::get_id() << std::endl;
    {
        HelloWorld item;
        item.start();
    }
    return(0);
}

Upvotes: 1

Views: 210

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

You have a race on *this, between the worker thread calling a virtual member function, and the main thread entering the destructor. This exhibits undefined behavior.

Practically speaking, the vtable pointer may already have been updated to that of Runnable, and the thread ends up calling a pure virtual function.

Upvotes: 4

Related Questions