我一直有一個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