在函数方法中使用std :: thread

时间:2016-02-10 15:36:00

标签: c++ multithreading c++11

这段代码按预期工作(它打印“procedure()”)

#include <iostream>
#include <thread>

class myClass{
public:
    myClass(){};
    ~myClass(){};
    void run(){std::cout << "run()"<<std::endl;};
    void procedure(){std::cout << "procedure()"<<std::endl;};
};


int main(int argc, char *argv[]){
    myClass* c = new myClass();
    std::thread c_thread(&myClass::procedure,c);
    c_thread.join();
    return 0;
}

现在我不喜欢调用者必须知道我的类启动一个线程的事实!所以我会优先在run方法的构造函数中隐藏启动线程。所以我写了下面的代码:

#include <iostream>
#include <thread>
class myClass{
public:
    myClass(){};
    ~myClass(){};
    void run(){
        std::cout << "run()"<<std::endl;
        std::thread c_thread(&myClass::procedure,this);     
    };
    void procedure(){std::cout << "procedure()"<<std::endl;};
};


int main(int argc, char *argv[]){
    myClass* c = new myClass();

    c->run();
    while(true){}

    return 0;
}

这最终会出现以下错误:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
run()
[New Thread 0x7ffff6fdd700 (LWP 4485)]
terminate called without an active exception

Program received signal SIGABRT, Aborted.
0x00007ffff70135f7 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.1.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64
(gdb) bt
#0  0x00007ffff70135f7 in raise () from /lib64/libc.so.6
#1  0x00007ffff7014ce8 in abort () from /lib64/libc.so.6
#2  0x00007ffff79179d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3  0x00007ffff7915946 in ?? () from /lib64/libstdc++.so.6
#4  0x00007ffff7915973 in std::terminate() () from /lib64/libstdc++.so.6
#5  0x000000000040109d in std::thread::~thread (this=0x7fffffffdeb0, __in_chrg=<optimized out>) at /usr/include/c++/4.8.2/thread:143
#6  0x00000000004011e1 in myClass::run (this=0x606010) at test2.cpp:9
#7  0x0000000000400f65 in main (argc=1, argv=0x7fffffffe008) at test2.cpp:17
(gdb) q
谁知道原因?

2 个答案:

答案 0 :(得分:5)

当你致电c->run();时,它会执行

void run(){
    std::cout << "run()"<<std::endl;
    std::thread c_thread(&myClass::procedure,this);     
};

当函数结束时c_thread被销毁。由于您从未在其上调用join()detach() c_thread仍然可以加入,这会导致析构函数抛出异常。见std::thread::~thread()

您需要让c_thread成为myClass的成员,并且在myClass析构函数中,您需要在其上调用join()detach()。这将允许销毁线程对象而不抛出异常。如果您致电join(),析构函数将不会在myClass::procedure结束前结束。如果你调用detach(),则析构函数将立即完成,但线程将继续运行,直到函数结束。

答案 1 :(得分:0)

c_thread超出范围whwn run()结束,因此线程被破坏,可能在procedure()完成之前。

我想你希望std::thread实例成为myClass的成员,而不是本地变量。在这种情况下,仅当c超出范围时才会销毁该线程。无论如何,thread.join()的析构函数中的myClass将等到线程完成。