多线程下boost::bind注意点

来源:互联网 时间:1970-01-01


最近发生一个异常中再次验证了“what(): boost::lock_error”属于对象成员“boost::mutex m_mtx” 被销毁后的调用引用的,有时也会伴随Segment fault的发生。

第一反应自然是悬空指针的调用问题,指针指向了一个被销毁的对象,并在某个时间调用这个不存在的对象。但在前几次排查中没有发现这个问题,因为我的对象生成后一直使用shared_ptr,于是把问题扩展化,反复调试和查看boost源代码,甚至一度怀疑库的问题?

事实再一次证明了一个观点,C++的库是经过严格考验,任何问题的发生只可能是人的问题,而不是库。案发现场如下:

 async_write
(
m_socket,
boost::asio::buffer(msg.c_str(), msg.size()),
bind
(
&Games::HandSend, this,
boost::asio::placeholders::error
)
);

上面这个例子是一个很常见的boost.asio的异步执行代码,如果没认真看很容易忽略了bind参数中的“this”参数,这正是当前对象的指针!异步执行过程中另一个线程会持有这个"this"指针并在未知的时间里回调HandSend方法,而在持有这个指针的时间内,这个线程并不知道当前对象有可能已经被销毁,所以造成很低级的悬空指针案件。

正确的做法应该是:

 async_write
(
m_socket,
boost::asio::buffer(msg.c_str(), msg.size()),
bind
(
&Games::HandSend, shared_from_this(),
boost::asio::placeholders::error
)
);

在asio中使用了shared_from_this智能指针,而且这个在asio中是必须使用的,否则几乎|肯定会发生问题。这又再次让我领略到在C++中使用裸指针的危害,只不过以往没有对"this"这个指向自身的指针有过足够的重视。


相关阅读:
Top