我在范围内使用char arry并将其绑定到ThreadPool
来执行任务,如下所示:
void test_thread_pool_arr(){
auto lb_print = [](const char* str){
info("print msg: %s, and i will sleep 2s", str);
sleep(2);
};
ThreadPool tp(3);
{
char arr[10];
memset(arr, '1', sizeof arr);
arr[9] = '\0';
tp.addTask(std::bind(lb_print, arr));
tp.addTask(std::bind(lb_print, arr));
} // leave scope so, arr should be invalid
info("leave scope....");
tp.exit(); // tell ThreadPool to join and then exit.
tp.join();
info("ending....");
}
输出如下:
2018/12/06-20:07:59 leave scope....
2018/12/06-20:07:59 print msg: 111111111, and i will sleep 2s
2018/12/06-20:07:59 print msg: 111111111, and i will sleep 2s
2018/12/06-20:08:01 ending....
我认为当arr离开它的作用域时,它应该被销毁,但是它的输出是正常的(任务函数lb_print只是获得了arr的地址,但是arr被销毁了)。
为什么? std :: bind是否会延长其寿命?如果是这样,它如何运作?
另一个带有类对象的示例:
class BindScope{
public:
BindScope(int i=0):n_(i){
info("BindScope ctor %d", n_);
}
~BindScope(){
info("BindScope ~dtor %d", n_);
}
void print()const{
info("do print %d", n_);
}
int n_;
};
void test_thread_pool_scope(){
auto lb_print = [](const BindScope& bs){
bs.print();
};
ThreadPool tp(3);
{
BindScope bs(4);
tp.addTask(std::bind(lb_print, std::ref(bs)));
tp.addTask(std::bind(lb_print, std::ref(bs)));
}// bs be destoryed, but tp do task normally
info("out scope");
tp.exit();
tp.join();
info("ending.........");
}
输出如下:
2018/12/06-20:14:03 BindScope ctor 4
2018/12/06-20:14:03 BindScope ~dtor 4
2018/12/06-20:14:03 out scope
2018/12/06-20:14:03 do print 4
2018/12/06-20:14:03 do print 4
2018/12/06-20:14:03 ending.........
我们可以看到,当对象bs
超出范围时,它会被破坏,但是ThreadPool
会正常执行任务。为什么?
答案 0 :(得分:2)
char数组的生存期没有延长,只是指向它的指针。
跟随悬空的指针,体验不确定的行为。
如果它是一个std数组,它将被复制。
未定义的行为可以做任何事情,包括“似乎正在工作”。
答案 1 :(得分:2)
实际上,这两种情况都会导致不确定的行为。您引用了悬空指针和悬空引用。任何事情都可能发生。在某些情况下,它可以“正常”运行。
答案 2 :(得分:0)
是的,它将引用悬挂指针。如下示例:
class BindScope{
public:
BindScope(int i=0):n_(i){
arr_ = new char[n_+1];
memset(arr_, '1', n_);
arr_[n_] = '\0';
info("BindScope ctor %d", n_);
}
~BindScope(){
info("BindScope ~dtor %d", n_);
delete[] arr_;
}
void print()const{
info("do print %d, %s", n_, arr_);
}
int n_;
char* arr_; // test for outof scope
};
void test_thread_pool_scope(){
auto lb_print = [](const BindScope& bs){
bs.print();
};
ThreadPool tp(3);
{
BindScope bs(4);
bs.print(); // test for normally output.
tp.addTask(std::bind(lb_print, std::ref(bs)));
tp.addTask(std::bind(lb_print, std::ref(bs)));
} // bs got destoryed.
info("out scope");
tp.exit();
tp.join();
info("ending.........");
}
输出如下:
2018/12/06-20:36:43 BindScope ctor 4
2018/12/06-20:36:43 do print 4, 1111 // output normal
2018/12/06-20:36:43 BindScope ~dtor 4
2018/12/06-20:36:43 out scope
2018/12/06-20:36:43 do print 4, // output wrong
2018/12/06-20:36:43 do print 4, // output wrong
2018/12/06-20:36:43 ending.........
我们可以看到,bs
的存储被还原后,ThreadPool
任务lb_print
的工作是错误的(outpur错误)。