std::thread causing application to abort with error R6010
I have a class named Task which internally holds a member std::thread. The general idea is to create a thread that stays alive as requests of processing come.
class Task
{
public:
    Task();
    ~Task();
    void start();
    // some funny stuff here
protected:
    Task(const Task& ref);
    void main_function();
    std::thread m_thread;
    // more funny stuff like queues, mutexes, etc
}
In the function start() I do:
void Task::start()
{
    m_thread = std::thread(std::bind(&Task::main_function, this));
}
The problem is that this line calls abort() with the runtime error R6010. I've read somewhere that this may be caused by the destructor of m_thread being called without a previous join but, as the thread hasn't started yet, I can't join it.
I'm running this with Visual Studio 2012
UPDATE:
So I tried a test example and could not replicate the error. Then I replaced my start function in the problematic function as sugested to this:
void Task::start()
{
    assert(!m_thread.joinable());
    m_thread = std::thread(&Task::main_function,this);
}
But I still get the error R6010. The call stack is:
msvcr110d.dll!_NMSG_WRITE(int rterrnum) Line 226    C
msvcr110d.dll!abort() Line 62   C
msvcr110d.dll!terminate() Line 97   C++
msvcp110d.dll!_Call_func(void * _Data) Line 63  C++
msvcr110d.dll!_callthreadstartex() Line 354 C
msvcr110d.dll!_threadstartex(void * ptd) Line 337   C
UPDATE2: Finally could replicate the problem. The code is as follows. Call foo() in the main function.
class Task 
{
public:
    Task() : m_exitFlag(false) 
    { 
        std::cout << "constructor called" << std::endl;
    }
    ~Task()
    {
        m_lock.lock();
        m_exitFlag = true;
        m_condlock.notify_all();
        m_lock.unlock();
        if (m_thread.joinable()) m_thread.join();
        std::cout << "destructor called" << std::endl;
     }
     void start()
     {
         std::cout << "Task start" << std::endl;
         assert(!m_thread.joinable());
         m_thread = std::thread(&Task::main_function, this);
     }
protected:
     void main_function()
     {
         std::cout << "thread started" << std::endl;
         while(1)
         {
             m_lock.lock();
             while(m_queue.empty() && !m_exitFlag)
                 m_condlock.wait(std::unique_lock<std::mutex>(m_lock));
             if (m_exitFlag)
             {
                 m_lock.unlock();
                 std::cout << "thread exiting" << std::endl;
                 return;
             }
             std::function<void()> f;
             if (!m_queue.empty()) f = m_queue.front();
             m_lock.unlock;
             if (f != nullptr) f();
         }
     }
     Task(const Task&ref) { }
     Task& operator=(const Task& ref) {
         return *this;
     }
};
void foo() {
    Task tk;
    tk.start();
}
I guess there's a race condition somewhere here, as it crashes some times and others don't. One thread is inside the critical region in ~Task() and the other as the stack in Update1.
 Never directly lock a mutex.  C++ offers lock_guard , unique_lock et al.  for a reason.  
In particular, this section is problematic:
m_lock.lock();
while(m_queue.empty() && !m_exitFlag)
    m_condlock.wait(std::unique_lock<std::mutex>(m_lock));
 The newly constructed unique_lock will attempt to lock the already locked mutex m_lock .  This will cause undefined behavior if the mutex is a std::mutex or a possible deadlock if the mutex is a std::recursive_mutex .  Also note that this line is relying on a non-standard compiler extension as you bind the unnamed unique_lock to a non- const reference when calling wait .  
 So first thing you have to do is make the lock a named variable.  Then either pass a std::adopt_lock to the lock's constructor or better yet never lock the mutex directly but always wrap it in an appropriate lock management class.  
For example,
m_lock.lock();
m_exitFlag = true;
m_condlock.notify_all();
m_lock.unlock();
becomes
{
    std::lock_guard<std::mutex> lk(m_lock);
    m_exitFlag = true;
    m_condlock.notify_all();
} // mutex is unlocked automatically as the lock_guard goes out of scope
This has the additional benefit that you won't leak locks if an exception is thrown inside the critical section.
It seems you take a function from the front() of the queue and then run the function after unlocking without first removing it from the queue with a pop(). Is this your intention? In such a case the next random thread may also acquire the same function and run it concurrently. Are those functions thread-safe? Also, you check for queue.empty() but where is the queue being emptied of functions after they are executed?
链接地址: http://www.djcxy.com/p/78932.html上一篇: 线程在编译或运行时确定?
