我一直有一个boost :: asio的问题,其中计时器和/或使用全局io_service实例创建的套接字在构建过程中崩溃。在发生崩溃的系统如下:在win_mutex锁boost :: asio :: io_service崩溃
Windows 7的
的Visual Studio 2013 Express的Windows桌面; v 12.0.31101.00 Update 4
Boost 1.57,动态链接,使用多线程编译,例如, boost_thread-VC120-MT-GD-1_57.dll
我已经能够复制问题在下面的简化代码:
//文件global_io_service.h
#ifndef INCLUDED_GLOBAL_IO_SERVICE_H
#define INCLUDED_GLOBAL_IO_SERVICE_H
#include <boost/asio/io_service.hpp>
#include <iostream>
#include <string>
namespace foo{
extern boost::asio::io_service test_io_service;
class foo_base_io_service{
public:
foo_base_io_service(const std::string& name)
: d_who_am_i(name)
{
std::cout << "constructing copy " << ++foo_base_io_service::num_instances << "my name is " << d_who_am_i << std::endl;
}
boost::asio::io_service& get_ref()
{
std::cout << "class requested copy of " << d_who_am_i << std::endl;
return d_ios;
}
~foo_base_io_service()
{
std::cout << "Someone 86'd the base_io_service..." << std::endl;
}
private:
// this class is not copyable
foo_base_io_service(const foo_base_io_service&);
foo_base_io_service& operator=(const foo_base_io_service&);
std::string d_who_am_i;
static int num_instances;
boost::asio::io_service d_ios;
};
extern foo_base_io_service global_timer_io_service;
} // namespace foo
#endif
//文件global_io_service.cpp
#include "global_io_service.h"
namespace foo{
boost::asio::io_service test_io_service;
foo_base_io_service global_timer_io_service("FOO_TIMER_SERVICE");
// static initialization
int foo_base_io_service::num_instances = 0;
}
//文件的main.cpp
#include <WinSock2.h>
#include "global_io_service.h"
#include <boost/asio/deadline_timer.hpp>
int main(int argc, char *argv[])
{
// also causes crash
boost::asio::deadline_timer crash_timer2(foo::test_io_service);
// causes crash
boost::asio::deadline_timer crash_timer(foo::global_timer_io_service.get_ref());
return 0 ;
}
这里是飞机坠毁的回溯:
test_io_service.exe提高:: ASIO ::详细:: win_mutex ::锁()线51
test_io_service.exe提升! :ASIO ::详细:: scoped_lock中:: scoped_lock的(提高:: ASIO ::详细:: win_mutex &米)47号线
test_io_service.exe提高:: ASIO ::详细:: win_iocp_io_service :: do_add_timer_queue(升压:: asio :: detail :: timer_queue_base & queue)Line 477
test_io_service.exe!提高:: ASIO ::详细:: win_iocp_io_service :: add_timer_queue>(升压:: ASIO ::详细:: timer_queue> &队列)线79
test_io_service.exe!升压:: ASIO ::详细:: deadline_timer_service> :: deadline_timer_service>(升压:: ASIO :: io_service对象& io_service对象)69号线
test_io_service.exe!提振:: ASIO :: deadline_timer_service> :: deadline_timer_service>(升压:: ASIO :: io_service & io_service)78行
test_io_service.exe!boost :: asio: :detail :: service_registry :: create >>>(boost :: asio :: io_service & owner)81行
test_io_service.exe!boost :: asio :: detail :: service_registry :: do_use_service(const boost :: asio :: io_service对象::服务::关键&键,提高:: ASIO :: io_service对象::服务*(升压:: ASIO :: io_service对象&)*工厂)线123
test_io_service.exe!提振:: ASIO :: detail :: service_registry :: use_service >>>()Line 49
test_io_service.exe!提高:: ASIO :: use_service>>(升压:: ASIO :: io_service对象& IOS)线34
test_io_service.exe!提振:: ASIO :: basic_io_object>,0> :: basic_io_object>,0>(升压:: ASIO :: io_service对象& io_service对象)线91
test_io_service.exe!提振:: ASIO :: basic_deadline_timer,提高:: ASIO :: deadline_timer_service>> :: basic_deadline_timer,提高:: ASIO :: deadline_timer_service>>(提高:: ASIO :: io_service对象& io_service对象)线151
test_io_service.exe!主(INT ARGC,CHAR *的argv)16号线C++
这是我学到的:
- 的问题不会在Ubuntu 14.04,Ubuntu的14.10或Red Hat 6.5,提升1.54发生。
- 此问题与Winsock2的加入顺序有关。例如,与global_io_service.h交换包含的顺序可消除崩溃。
- 此问题与global_timer_io_service的外部链接有关。将global_timer_io_service的定义移动到main.cpp中可消除崩溃。
- 我发现了在io_service内部关键部分发生类似崩溃的报告。这些问题主要与传递到定时器/套接字构造函数的io_service对象的生命周期有关。就我而言,我认为我使用的io_service在输入main之前已经构建完成。
- 我的直觉说,有一个竞争条件(可能是WinSock2中的一些全局状态设置?),阻止正确构建io_service对象。
希望我今天过得不好,并且调用未定义的行为。 否则,我想了解为什么会发生这种情况?提前致谢。
我的直觉说它是[静态初始化Fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order)比(线程)数据竞争更快。 – sehe
@sehe同意。作为一个可能的原因,失败是有道理的。更改foo_base_io_service的链接和交换标头包含顺序都可以触发静态初始化排序中的更改。 – lukecfg
@lukecfg,到目前为止的任何解决方案? – Jithendra