下面发布的代码中的奇怪行为导致对象析构函数被多次调用。虽然代码没有因此而崩溃,但我只想找出这种行为发生的原因。这是一个非常简单的正常程序模板,很可能是Boost所有人都使用过的,但直到现在我才注意到这种行为。
#include <boost/thread.hpp>
#include <iostream>
class object
{
private:
int value;
public:
object();
~object();
void pass( int value);
};
object::object()
{
std::cout<<"constructing object: "<<this<<" with value: "<<this->object::value<<std::endl;
}
object::~object()
{
std::cout<<"destructing object: "<<this<<" with value: "<<this->object::value<<std::endl;
}
void object::pass( int value)
{
this->object::value = value;
std::cout<<"value passed is: "<<this->object::value<<std::endl;
}
class threaded
{
private:
object A;
public:
threaded();
~threaded();
void init( int value);
};
threaded::threaded(){}
threaded::~threaded(){}
void threaded::init( int value)
{
this->threaded::A.pass( value);
}
int main()
{
threaded T;
int unlucky_number = 13;
boost::thread_group tg;
tg.add_thread( new boost::thread( boost::bind( &threaded::init, T, unlucky_number)));
tg.join_all();
return 0;
}
这是代码输出。
constructing object: 0x7ffcb53157f0 with value: 0
destructing object: 0x7ffcb53156d0 with value: 0 <----From here?
destructing object: 0x7ffcb5315720 with value: 0
destructing object: 0x7ffcb53157a0 with value: 0
destructing object: 0x7ffcb5315780 with value: 0
destructing object: 0x7ffcb5315710 with value: 0
destructing object: 0x7ffcb53157c0 with value: 0
destructing object: 0x7ffcb5315820 with value: 0
destructing object: 0x7ffcb5315800 with value: 0 <----To here?
value passed is: 13
destructing object: 0x1a5f2d8 with value: 13
destructing object: 0x7ffcb53157f0 with value: 0
在第一个构造之后和行 value passed is: 13
之前销毁的对象必须以某种方式由boost线程库中的复制构造函数创建,但为什么它们从未构造,为什么没撞车?再加上他们的价值总是零,所以这不是垃圾记忆......任何想法?
所以应G.M.的要求我尝试创建复制构造函数只是为了在error_code.hpp中获得与boost相关的错误。
这是新代码加上编译它的错误。
#include <boost/thread.hpp>
#include <iostream>
class object
{
private:
int value;
public:
object();
object( object const ©_this);
~object();
void pass( int value);
};
object::object()
{
std::cout<<"constructing object: "<<this<<" with value: "<<this->object::value<<std::endl;
}
object::object( object const ©_this)
{
std::cout<<"object copy constructor. "<<std::endl;
this->object::value = copy_this.value;
}
object::~object()
{
std::cout<<"destructing object: "<<this<<" with value: "<<this->object::value<<std::endl;
}
void object::pass( int value)
{
this->object::value = value;
std::cout<<"value passed is: "<<this->object::value<<std::endl;
}
class threaded
{
private:
object A;
public:
threaded();
threaded( threaded const ©_this);
~threaded();
void init( int value);
};
threaded::threaded(){}
threaded::threaded( threaded const ©_this)
{
std::cout<<"threaded copy constructor. "<<std::endl;
this->threaded::A = copy_this.A;
}
threaded::~threaded(){}
void threaded::init( int value)
{
this->threaded::A.pass( value);
}
int main()
{
threaded T;
int unlucky_number = 13;
boost::thread_group tg;
tg.add_thread( new boost::thread( boost::bind( &threaded::init, T, unlucky_number)));
tg.join_all();
//T.init(13);
return 0;
}
||=== Build: Debug in boost_thread_destructor_problem (compiler: GNU GCC Compiler) ===|
obj/Debug/boost_thread_destructor_problem.o||In function `__static_initialization_and_destruction_0(int, int)':|
/usr/include/boost/system/error_code.hpp|221|undefined reference to `boost::system::generic_category()'|
/usr/include/boost/system/error_code.hpp|222|undefined reference to `boost::system::generic_category()'|
/usr/include/boost/system/error_code.hpp|223|undefined reference to `boost::system::system_category()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::thread_exception::thread_exception(int, char const*)':|
/usr/include/boost/thread/exceptions.hpp|51|undefined reference to `boost::system::system_category()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::condition_error::condition_error(int, char const*)':|
/usr/include/boost/thread/exceptions.hpp|84|undefined reference to `boost::system::system_category()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::detail::thread_data_base::thread_data_base()':|
/usr/include/boost/thread/pthread/thread_data.hpp|152|undefined reference to `vtable for boost::detail::thread_data_base'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::detail::interruption_checker::interruption_checker(pthread_mutex_t*, pthread_cond_t*)':|
/usr/include/boost/thread/pthread/thread_data.hpp|195|undefined reference to `boost::detail::get_current_thread_data()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::thread::start_thread()':|
/usr/include/boost/thread/detail/thread.hpp|179|undefined reference to `boost::thread::start_thread_noexcept()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::thread::~thread()':|
/usr/include/boost/thread/detail/thread.hpp|254|undefined reference to `boost::thread::detach()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::thread::get_id() const':|
/usr/include/boost/thread/detail/thread.hpp|741|undefined reference to `boost::thread::native_handle()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::thread::join()':|
/usr/include/boost/thread/detail/thread.hpp|767|undefined reference to `boost::thread::join_noexcept()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::condition_variable::wait(boost::unique_lock<boost::mutex>&)':|
/usr/include/boost/thread/pthread/condition_variable.hpp|84|undefined reference to `boost::this_thread::interruption_point()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::shared_mutex::lock_shared()':|
/usr/include/boost/thread/pthread/shared_mutex.hpp|186|undefined reference to `boost::this_thread::disable_interruption::disable_interruption()'|
/usr/include/boost/thread/pthread/shared_mutex.hpp|186|undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'|
/usr/include/boost/thread/pthread/shared_mutex.hpp|186|undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::shared_mutex::lock()':|
/usr/include/boost/thread/pthread/shared_mutex.hpp|287|undefined reference to `boost::this_thread::disable_interruption::disable_interruption()'|
/usr/include/boost/thread/pthread/shared_mutex.hpp|287|undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'|
/usr/include/boost/thread/pthread/shared_mutex.hpp|287|undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::thread_group::join_all()':|
/usr/include/boost/thread/detail/thread_group.hpp|117|undefined reference to `boost::thread::joinable() const'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf1<void, threaded, int>, boost::_bi::list2<boost::_bi::value<threaded>, boost::_bi::value<int> > > >::thread_data(boost::_bi::bind_t<void, boost::_mfi::mf1<void, threaded, int>, boost::_bi::list2<boost::_bi::value<threaded>, boost::_bi::value<int> > >)':|
/usr/include/boost/thread/detail/thread.hpp|109|undefined reference to `boost::detail::thread_data_base::~thread_data_base()'|
obj/Debug/boost_thread_destructor_problem.o||In function `boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf1<void, threaded, int>, boost::_bi::list2<boost::_bi::value<threaded>, boost::_bi::value<int> > > >::~thread_data()':|
/usr/include/boost/thread/detail/thread.hpp|90|undefined reference to `boost::detail::thread_data_base::~thread_data_base()'|
/usr/include/boost/thread/detail/thread.hpp|90|undefined reference to `boost::detail::thread_data_base::~thread_data_base()'|
obj/Debug/boost_thread_destructor_problem.o:(.rodata._ZTIN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf1Iv8threadediEENS2_5list2INS2_5valueIS6_EENS9_IiEEEEEEEE[_ZTIN5boost6detail11thread_dataINS_3_bi6bind_tIvNS_4_mfi3mf1Iv8threadediEENS2_5list2INS2_5valueIS6_EENS9_IiEEEEEEEE]+0x10)||undefined reference to `typeinfo for boost::detail::thread_data_base'|
||error: ld returned 1 exit status|
||=== Build failed: 24 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|
答案 0 :(得分:3)
您可以通过避免bind
来缓解这一问题。 Lambdas解决了这个问题 - 通常更有效率:
tg.create_thread([=]() mutable { T.init(unlucky_number); });
在C ++ 14中can be a bit more advanced:
tg.create_thread([T=std::move(T), unlucky_number = 13]() mutable { T.init(unlucky_number); });
如果object
复制费用昂贵,请考虑让其移动感知,例如
object(object const&) = default;
object(object&&) = default;
object& operator=(object&&) = default;
确保编译器生成特殊成员,即使您添加了用户声明的(非平凡的)构造函数/析构函数成员。
答案 1 :(得分:2)
由于您调用boost::bind
...
tg.add_thread(new boost::thread(boost::bind(&threaded::init, T, unlucky_number)));
T
将按值传递。这可能会导致T
实施boost::bind
执行T
的任何数量的复制。
由于您知道tg.add_thread(new boost::thread(boost::bind(&threaded::init, boost::ref(T), unlucky_number)));
在这种情况下会比使用它的线程更长,您可以通过引用强制传递...
tg.add_thread(new boost::thread(boost::bind(&threaded::init, &T, unlucky_number)));
或传递指针......
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<Table>
<Name/>
<Location/>
<Citation>
<Title />
<Abstract />
<Description/>
</Citation>
<metadataDate/>
</Table>
</metadata>